some bugs fixed
[tomamp] / playlistmanager.cpp
1 #include "playlistmanager.h"
2 #include <QDir>
3 #include <QUrl>
4 #include <QMap>
5
6 PlaylistManager::PlaylistManager(QWidget* parent)
7     : parentWidget (parent)
8 {
9     metaInformationResolver = new Phonon::MediaObject(parent);
10     connect(metaInformationResolver, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
11         this, SLOT(metaStateChanged(Phonon::State,Phonon::State)));
12 }
13
14 int PlaylistManager::indexOf(const Phonon::MediaSource &s) const
15 {
16     for (int i = 0; i < items.size(); ++i)
17     {
18         if (items[i].source == s)
19             return i;
20     }
21     return -1;
22 }
23
24 void PlaylistManager::parseAndAddFolder(const QString &dir, bool recursive)
25 {
26     QStringList filters;
27 //    filters << "*.mp3";
28
29     QStringList files = QDir (dir).entryList(filters);
30
31     if (files.isEmpty())
32         return;
33
34     qDebug () << "Parsing folder " << dir;
35
36     //settings.setValue("LastFolder", dir);
37     int index = items.size();
38     foreach (QString string, files)
39     {
40         if (string == "."  || string == "..")
41             continue;
42         QString fname = dir + "/" + string;
43         QFileInfo fi (fname);
44         if (fi.isDir())
45         {
46             if (recursive)
47                 parseAndAddFolder(fname, true);
48             continue;
49         }
50         if (fileSupported(fname))
51         {
52             qDebug () << "Adding: " << fname;
53             items.append(PlaylistItem (PlaylistItem (fname)));
54         }
55     }
56     if (!items.isEmpty())
57         metaInformationResolver->setCurrentSource(items.at(index).source);
58     qDebug () << " SIZE: " << items.size ();
59     emit playlistChanged (index);
60 }
61
62 void PlaylistManager::addStringList(const QStringList& list)
63 {
64     int index = items.size();
65     foreach (QString string, list)
66     {
67         if (fileSupported(string) || string.toLower().startsWith("http"))
68         {
69             qDebug () << "Adding " << string;
70             items.append(PlaylistItem (string));
71         }
72     }
73     if (!items.isEmpty())
74         metaInformationResolver->setCurrentSource(items.at(index).source);
75     emit playlistChanged(index);
76 }
77
78 void PlaylistManager::metaStateChanged(Phonon::State newState, Phonon::State oldState)
79 {
80     qDebug () << "Meta state now " << newState << " old state " << oldState;
81     if (oldState == Phonon::ErrorState)
82     {
83 /*        int index = indexOf (metaInformationResolver->currentSource());
84         metaInformationResolver->setCurrentSource(items[index].source);*/
85     }
86     if (newState == Phonon::ErrorState)
87     {
88         int index = indexOf (metaInformationResolver->currentSource());
89         if (index >= 0 && items.size () > index + 1)
90         {
91 /*            metaInformationResolver->disconnect();
92             delete metaInformationResolver;
93             metaInformationResolver = new Phonon::MediaObject(parent());
94             connect(metaInformationResolver, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
95                 this, SLOT(metaStateChanged(Phonon::State,Phonon::State)));*/
96             metaInformationResolver->setCurrentSource(items[index + 1].source);
97 //            metaInformationResolver->clear();
98             qDebug () << "Set " << items[index + 1].source.fileName() << " error type: " << metaInformationResolver->errorString() << " (" << metaInformationResolver->errorType() << ")";
99         }
100         qDebug () << "Error for item " << index;
101         return;
102     }
103
104     if (newState != Phonon::StoppedState/* && newState != Phonon::PausedState*/)
105     {
106         return;
107     }
108
109     if (metaInformationResolver->currentSource().type() == Phonon::MediaSource::Invalid)
110         return;
111     int index = indexOf (metaInformationResolver->currentSource());
112     qDebug () << "Reading meta info of " << metaInformationResolver->currentSource().fileName() << " => " << index;
113
114     QMap<QString, QString> metaData = metaInformationResolver->metaData();
115
116
117     if (index >= 0)
118     {
119         items[index].artist = metaData.value("ARTIST");
120         items[index].title = metaData.value("TITLE");
121         items[index].album = metaData.value("ALBUM");
122         qDebug () << "Info is: " << items[index].artist << " - " << items[index].title;
123         if (metaData.isEmpty())
124             qDebug () << "Detected to be empty: " << items[index].uri;
125         else
126             items[index].playable = true;
127         emit itemUpdated (index);
128         if (index >= 0 && items.size () > index + 1)
129             metaInformationResolver->setCurrentSource(items[index + 1].source);
130     }
131 }
132
133 void PlaylistManager::savePlaylist(const QString& filenam)
134 {
135     QString filename = filenam;
136     if (filename.isEmpty())
137         return;
138     bool writepls = false;
139     if (filename.length() < 4 || (filename.right(4).toLower() != ".m3u" && filename.right(4).toLower() != ".pls"))
140     {
141         filename += ".pls";
142         writepls = true;
143     }
144     else if (filename.right(4).toLower() == ".pls")
145         writepls = true;
146     QFile f (filename);
147     try
148     {
149         f.open(QFile::WriteOnly);
150         if (writepls)
151         {
152             f.write ("[playlist]\n");
153             f.write (QString ("NumberOfEntries=%1\n").arg (items.size ()).toAscii());
154         }
155         for (int i = 0; i < items.size(); ++i)
156         {
157             if (writepls)
158             {
159                 f.write (QString ("File%1=%2\n").arg (i + 1).arg (items[i].uri).toAscii());
160                 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());
161             }
162             else
163             {
164                 f.write (items[i].uri.toAscii());
165                 f.write ("\n");
166             }
167         }
168         if (writepls)
169             f.write ("Version=2\n");
170         f.close ();
171     }
172     catch (...)
173     {
174 //        QMessageBox::critical(this, "Write error", "Could not write playlist file", QMessageBox::Ok);
175     }
176 }
177
178 void PlaylistManager::loadPlaylist(const QString& filename)
179 {
180     clearPlaylist();
181     if (filename.right(4).toLower() == ".m3u")
182         appendPlaylist(filename);
183     else if (filename.right(4).toLower() == ".pls")
184         appendPlaylistPLS(filename);
185     if (!items.isEmpty())
186     {
187         metaInformationResolver->setCurrentSource(items.at(0).source);
188     }
189     emit playlistChanged (0);
190 }
191
192 void PlaylistManager::addPlaylist(const QString& filename)
193 {
194     int index = items.size();
195     if (filename.right(4).toLower() == ".m3u")
196         appendPlaylist(filename);
197     else if (filename.right(4).toLower() == ".pls")
198         appendPlaylistPLS(filename);
199     if (!items.isEmpty())
200     {
201         metaInformationResolver->setCurrentSource(items.at(index).source);
202         emit playlistChanged (index);
203     }
204 }
205
206 void PlaylistManager::appendPlaylist(const QString& filename)
207 {
208     qDebug () << "Attempting to load playlist: " << filename;
209     QFile f(filename);
210     if (!f.open (QFile::ReadOnly))
211         return;
212     QString tmp = f.readAll();
213     f.close ();
214     QStringList lines = tmp.split("\n");
215     foreach (QString l, lines)
216     {
217         if (l.isEmpty() || (!QFileInfo (l).exists() && (l.indexOf("http") != 0)))
218         {
219             continue;
220         }
221         qDebug () << "Load " << l;
222         items.append(PlaylistItem (l));
223     }
224 }
225
226 void PlaylistManager::appendPlaylistPLS(const QString& filename)
227 {
228     qDebug () << "Attempting to load playlist: " << filename;
229     QFile f(filename);
230     if (!f.open (QFile::ReadOnly))
231         return;
232     QString tmp = f.readAll();
233     f.close ();
234     QStringList lines = tmp.split("\n");
235     QMap<int, int> filemap;
236
237     foreach (QString l, lines)
238     {
239         if (l.isEmpty() || l.trimmed().toLower() == "[playlist]" || l.trimmed().toLower() == "version=2")
240         {
241             continue;
242         }
243         qDebug () << "PLS " << l;
244         if (l.trimmed().toLower().left(4) == "file")
245         {
246             QStringList tokens = l.split('=');
247             if (tokens.size () < 2)
248                 continue;
249             tokens[0] = tokens[0].mid (4);
250             filemap.insert(tokens[0].toInt (), items.size ());
251             qDebug () << tokens;
252             items.append(PlaylistItem (tokens[1]));
253         }
254         else if (l.trimmed().toLower().left(5) == "title")
255         {
256             QStringList tokens = l.split('=');
257             if (tokens.size () < 2)
258                 continue;
259             tokens[0] = tokens[0].mid (5);
260             int toupdate = filemap[tokens[0].toInt()];
261             qDebug () << "Need to update " << toupdate << " for " << l;
262             QStringList metatok = tokens[1].split (" - ");
263             qDebug () << metatok;
264             if (metatok.size() > 2 && toupdate >= 0 && toupdate < items.size ())
265             {
266                 items[toupdate].artist = metatok[0];
267                 items[toupdate].title = metatok[1];
268                 metatok = metatok.mid (2);
269                 items[toupdate].album = metatok.join (" - ");
270             }
271             else
272             {
273                 items[toupdate].title = metatok.join (" - ");
274             }
275         }
276     }
277 }
278
279
280 void PlaylistManager::clearPlaylist()
281 {
282     items.clear();
283     emit playlistChanged(0);
284 /*    while (musicTable->rowCount())
285         musicTable->removeRow(0);
286     mediaObject->clear();*/
287 }
288
289 QStringList PlaylistManager::playlistStrings() const
290 {
291     QStringList ret;
292     for (int i = 0; i < items.size (); ++i)
293         ret << items[i].uri;
294     qDebug () << "Returning playlist " << ret << " SIZE: " << items.size ();
295     return ret;
296 }
297
298 void PlaylistManager::removeItem(int i)
299 {
300     items.removeAt (i);
301     emit playlistChanged(i);
302 }
303
304 bool PlaylistManager::fileSupported (const QString& fname) const
305 {
306     QString ext = fname.right(3).toLower();
307 //    if (ext != "mp3")
308 //        return false;
309     return true;
310 }