1 #include "playlistmanager.h"
5 #include <QTemporaryFile>
6 #include <QtNetwork/QNetworkAccessManager>
7 #include <QtNetwork/QNetworkReply>
9 QStringList PlaylistManager::allowedExtensions;
12 PlaylistManager::PlaylistManager(QWidget* parent)
13 : parentWidget (parent), lastMetaRead (-1)
15 if (!allowedExtensions.size ())
17 allowedExtensions << "mp3" << "ogg" << "wav" << "mlp" << "wma" << "flac" << "amr";
18 allowedExtensions << "midi" << "mid" << "mpeg" << "qcp" << "ac3" << "aiff" << "act";
19 allowedExtensions << "alac" << "alaw" << "au" << "eac3" << "aac" << "ape" << "gsm";
20 allowedExtensions << "mod" << "mp2" << "sbc" << "spx" << "tta" << "ra" << "riff";
21 allowedExtensions << "m4a" << "mp4" << "m4p" << "pcm" << "amr";
23 metaInformationResolver = new Phonon::MediaObject(parent);
24 connect(metaInformationResolver, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
25 this, SLOT(metaStateChanged(Phonon::State,Phonon::State)));
26 downloadmanager = new QNetworkAccessManager(this);
27 connect(downloadmanager, SIGNAL(finished(QNetworkReply*)),
28 this, SLOT(playlistDownloadFinished(QNetworkReply*)));
31 int PlaylistManager::indexOf(const Phonon::MediaSource &s) const
33 for (int i = 0; i < items.size(); ++i)
35 if (items[i].source == s)
41 void PlaylistManager::parseAndAddFolder(const QString &dir, bool recursive)
45 QStringList files = QDir (dir).entryList(filters);
51 int index = items.size();
52 foreach (QString string, files)
54 if (string == "." || string == "..")
56 QString fname = dir + "/" + string;
61 parseAndAddFolder(fname, true);
64 if (fileSupported(fname))
66 qDebug () << "Adding: " << fname;
67 items.append(PlaylistItem (PlaylistItem (fname)));
70 if (items.size () > index)
72 metaInformationResolver->setCurrentSource(items.at(index).source);
75 emit playlistChanged (index);
78 void PlaylistManager::addStringList(const QStringList& list)
80 int index = items.size();
81 foreach (QString string, list)
83 if (fileSupported(string) || string.toLower().startsWith("http"))
85 if (string.toLower().startsWith("http") && ((string.toLower().endsWith("pls")
86 || (string.toLower().endsWith("m3u")))))
88 downloadmanager->get(QNetworkRequest(QUrl(string)));
92 items.append(PlaylistItem (string));
96 if (items.size () > index)
98 metaInformationResolver->setCurrentSource(items.at(index).source);
101 emit playlistChanged(index);
104 void PlaylistManager::playlistDownloadFinished(QNetworkReply* rep)
108 tmp.write (rep->readAll());
110 QString filename = tmp.fileName();
111 int index = items.size();
112 if (rep->url().toString().right(4).toLower() == ".m3u")
113 appendPlaylist(filename);
114 else if (rep->url().toString().right(4).toLower() == ".pls")
115 appendPlaylistPLS(filename);
116 if (items.size () > index)
118 metaInformationResolver->setCurrentSource(items.at(index).source);
119 lastMetaRead = index;
120 emit playlistChanged (index);
125 void PlaylistManager::metaStateChanged(Phonon::State newState, Phonon::State /*oldState*/)
127 // NOTE: This is an ugly hack, since the metaInformationResolver doesn't properly load the assigned source when it's in the error state
128 // In order to properly read the next file we have to set it as current source again when the resolver entered the stopped state after the error
129 static bool wasError = false;
130 if (wasError && newState == Phonon::StoppedState)
132 metaInformationResolver->setCurrentSource(items[lastMetaRead].source);
136 if (newState == Phonon::ErrorState)
141 if (newState != Phonon::StoppedState && newState != Phonon::ErrorState)
146 int index = lastMetaRead;
148 QMap<QString, QString> metaData = metaInformationResolver->metaData();
151 if (index >= 0 && newState != Phonon::ErrorState && index < items.size ())
153 items[index].artist = metaData.value("ARTIST");
154 items[index].title = metaData.value("TITLE");
155 items[index].album = metaData.value("ALBUM");
156 /* items[index].year = metaData.value("DATE");
157 items[index].genre = metaData.value("GENRE");
158 qDebug () << "Meta " << metaData;
159 qDebug () << "Info is: " << items[index].year << " - " << items[index].genre;*/
160 if (!metaData.isEmpty())
161 items[index].playable = true;
162 emit itemUpdated (index);
164 if (index >= 0 && items.size () > index + 1)
166 metaInformationResolver->setCurrentSource(items[index + 1].source);
167 lastMetaRead = index + 1;
171 bool PlaylistManager::savePlaylist(const QString& filenam)
173 QString filename = filenam;
174 if (filename.isEmpty())
176 bool writepls = false;
177 if (filename.length() < 4 || (filename.right(4).toLower() != ".m3u" && filename.right(4).toLower() != ".pls"))
182 else if (filename.right(4).toLower() == ".pls")
187 f.open(QFile::WriteOnly);
190 f.write ("[playlist]\n");
191 f.write (QString ("NumberOfEntries=%1\n").arg (items.size ()).toAscii());
193 for (int i = 0; i < items.size(); ++i)
197 f.write (QString ("File%1=%2\n").arg (i + 1).arg (items[i].uri).toAscii());
198 f.write (QString ("Title%1=%2 - %3 - %4\n").arg (i + 1).arg (items[i].artist).arg (items[i].title).arg (items[i].album).toAscii());
202 f.write (items[i].uri.toAscii());
207 f.write ("Version=2\n");
217 void PlaylistManager::loadPlaylist(const QString& filename)
220 if (filename.right(4).toLower() == ".m3u")
221 appendPlaylist(filename);
222 else if (filename.right(4).toLower() == ".pls")
223 appendPlaylistPLS(filename);
224 if (!items.isEmpty())
226 metaInformationResolver->setCurrentSource(items.at(0).source);
229 emit playlistChanged (0);
232 void PlaylistManager::addPlaylist(const QString& filename)
234 int index = items.size();
235 if (filename.right(4).toLower() == ".m3u")
236 appendPlaylist(filename);
237 else if (filename.right(4).toLower() == ".pls")
238 appendPlaylistPLS(filename);
239 if (items.size () > index)
241 metaInformationResolver->setCurrentSource(items.at(index).source);
242 lastMetaRead = index;
243 emit playlistChanged (index);
247 void PlaylistManager::appendPlaylist(const QString& filename)
250 if (!f.open (QFile::ReadOnly))
252 QString tmp = f.readAll();
254 QStringList lines = tmp.split("\n");
255 foreach (QString l, lines)
257 if (l.isEmpty() || (!QFileInfo (l).exists() && (l.indexOf("http") != 0))
258 || l.trimmed().startsWith("#"))
262 l = l.replace("\r", "");
263 items.append(PlaylistItem (l));
267 void PlaylistManager::appendPlaylistPLS(const QString& filename)
270 if (!f.open (QFile::ReadOnly))
272 QString tmp = f.readAll();
274 QStringList lines = tmp.split("\n");
275 QMap<int, int> filemap;
277 foreach (QString l, lines)
279 if (l.isEmpty() || l.trimmed().toLower() == "[playlist]" || l.trimmed().toLower() == "version=2"
280 || l.trimmed().startsWith(";"))
284 l = l.replace("\r", "");
285 if (l.trimmed().toLower().left(4) == "file")
287 QStringList tokens = l.split('=');
288 if (tokens.size () < 2)
290 tokens[0] = tokens[0].mid (4);
291 filemap.insert(tokens[0].toInt (), items.size ());
292 items.append(PlaylistItem (tokens[1]));
294 else if (l.trimmed().toLower().left(5) == "title")
296 QStringList tokens = l.split('=');
297 if (tokens.size () < 2)
299 tokens[0] = tokens[0].mid (5);
300 int toupdate = filemap[tokens[0].toInt()];
301 QStringList metatok = tokens[1].split (" - ");
302 if (metatok.size() > 2 && toupdate >= 0 && toupdate < items.size ())
304 items[toupdate].artist = metatok[0];
305 items[toupdate].title = metatok[1];
306 metatok = metatok.mid (2);
307 items[toupdate].album = metatok.join (" - ");
311 items[toupdate].title = metatok.join (" - ");
318 void PlaylistManager::clearPlaylist()
321 emit playlistChanged(0);
324 QStringList PlaylistManager::playlistStrings() const
327 for (int i = 0; i < items.size (); ++i)
332 void PlaylistManager::removeItem(int i)
339 bool PlaylistManager::fileSupported (const QString& fname) const
341 if (fname.lastIndexOf('.') < 0)
343 QString ext = fname.right(fname.size() - fname.lastIndexOf('.') - 1).toLower();
344 foreach (QString e, allowedExtensions)
353 bool PlaylistManager::moveItemUp (int i)
357 PlaylistItem tmp = items[i - 1];
358 items[i - 1] = items[i];
365 bool PlaylistManager::moveItemDown (int i)
367 if (i < items.size () - 1)
369 PlaylistItem tmp = items[i + 1];
370 items[i + 1] = items[i];