diff -ru ../123/mythplugins/mythmusic/mythmusic/main.cpp mythplugins/mythmusic/mythmusic/main.cpp
old
|
new
|
|
6 | 6 | #include <qapplication.h> |
7 | 7 | #include <qsqldatabase.h> |
8 | 8 | #include <qregexp.h> |
| 9 | #include <sys/types.h> |
| 10 | #include <sys/stat.h> |
9 | 11 | #include <unistd.h> |
10 | 12 | |
11 | 13 | #include <cdaudio.h> |
… |
… |
|
93 | 95 | query.exec(); |
94 | 96 | } |
95 | 97 | |
| 98 | void UpdateFileInDB (const QString &directory, const QString &filename) |
| 99 | { |
| 100 | Decoder *decoder = getDecoder (filename); |
| 101 | |
| 102 | if (decoder) |
| 103 | { |
| 104 | Metadata *db_meta = decoder->getMetadata (); |
| 105 | Metadata *disk_meta = decoder->readMetadata (); |
| 106 | |
| 107 | if (db_meta && disk_meta) |
| 108 | { |
| 109 | disk_meta->setID (db_meta->ID ()); |
| 110 | disk_meta->updateDatabase (directory); |
| 111 | } |
| 112 | |
| 113 | if (disk_meta) |
| 114 | delete disk_meta; |
| 115 | |
| 116 | if (db_meta) |
| 117 | delete db_meta; |
| 118 | |
| 119 | delete decoder; |
| 120 | } |
| 121 | } |
| 122 | |
96 | 123 | enum MusicFileLocation |
97 | 124 | { |
98 | 125 | kFileSystem, |
99 | 126 | kDatabase, |
| 127 | kNeedUpdate, |
100 | 128 | kBoth |
101 | 129 | }; |
102 | 130 | |
… |
… |
|
139 | 167 | } |
140 | 168 | } |
141 | 169 | |
| 170 | bool HasFileChanged (const QString &filename, const QString &date_modified) |
| 171 | { |
| 172 | struct stat sbuf; |
| 173 | if (stat (filename.ascii (), &sbuf) == 0) { |
| 174 | if (sbuf.st_mtime > (time_t)QDateTime::fromString (date_modified, |
| 175 | Qt::ISODate).toTime_t ()) { |
| 176 | return true; |
| 177 | } |
| 178 | } |
| 179 | return false; |
| 180 | } |
| 181 | |
142 | 182 | void SavePending(int pending) |
143 | 183 | { |
144 | 184 | // Temporary Hack until mythmusic |
… |
… |
|
208 | 248 | delete busy; |
209 | 249 | |
210 | 250 | MSqlQuery query(MSqlQuery::InitCon()); |
211 | | query.exec("SELECT filename FROM musicmetadata " |
| 251 | query.exec("SELECT filename, date_modified FROM musicmetadata " |
212 | 252 | "WHERE filename NOT LIKE ('%://%');"); |
213 | 253 | |
214 | 254 | int counter = 0; |
… |
… |
|
224 | 264 | QString name = directory + QString::fromUtf8(query.value(0).toString()); |
225 | 265 | if (name != QString::null) |
226 | 266 | { |
227 | | if ((iter = music_files.find(name)) != music_files.end()) |
228 | | music_files.remove(iter); |
229 | | else |
| 267 | if ((iter = music_files.find(name)) != music_files.end()) { |
| 268 | if (HasFileChanged(name, query.value(1).toString())) { |
| 269 | music_files[name] = kNeedUpdate; |
| 270 | } else { |
| 271 | music_files.remove(iter); |
| 272 | } |
| 273 | } else { |
230 | 274 | music_files[name] = kDatabase; |
| 275 | } |
231 | 276 | } |
232 | 277 | file_checking->setProgress(++counter); |
233 | 278 | } |
… |
… |
|
239 | 284 | file_checking = new MythProgressDialog(QObject::tr("Updating music database"), |
240 | 285 | music_files.size()); |
241 | 286 | |
242 | | QRegExp quote_regex("\""); |
| 287 | /* |
| 288 | This can be optimised quite a bit by consolidating all commands |
| 289 | via a lot of refactoring. |
| 290 | |
| 291 | 1) group all files of the same decoder type, and don't |
| 292 | create/delete a Decoder pr. AddFileToDB. Or make Decoders be |
| 293 | singletons, it should be a fairly simple change. |
| 294 | |
| 295 | 2) RemoveFileFromDB should group the remove into one big SQL. |
| 296 | |
| 297 | 3) UpdateFileInDB, same as 1. |
| 298 | */ |
| 299 | |
243 | 300 | for (iter = music_files.begin(); iter != music_files.end(); iter++) |
244 | 301 | { |
245 | 302 | if (*iter == kFileSystem) |
246 | 303 | AddFileToDB(directory, iter.key()); |
247 | 304 | else if (*iter == kDatabase) |
248 | 305 | RemoveFileFromDB(directory, iter.key ()); |
| 306 | else if (*iter == kNeedUpdate) |
| 307 | UpdateFileInDB(directory, iter.key ()); |
249 | 308 | |
250 | 309 | file_checking->setProgress(++counter); |
251 | 310 | } |
… |
… |
|
301 | 360 | AllMusic *all_music; |
302 | 361 | }; |
303 | 362 | |
| 363 | void RebuildMusicTree (MusicData *mdata) { |
| 364 | MythBusyDialog busy (QObject::tr("Rebuilding music tree")); |
| 365 | busy.start (); |
| 366 | mdata->all_music->startLoading (); |
| 367 | while (!mdata->all_music->doneLoading ()) { |
| 368 | qApp->processEvents (); |
| 369 | usleep (50000); |
| 370 | } |
| 371 | mdata->all_playlists->postLoad(); |
| 372 | busy.Close (); |
| 373 | } |
| 374 | |
304 | 375 | void MusicCallback(void *data, QString &selection) |
305 | 376 | { |
306 | 377 | MusicData *mdata = (MusicData *)data; |
… |
… |
|
320 | 391 | // Reconcile with the database |
321 | 392 | SearchDir(mdata->startdir); |
322 | 393 | // Tell the metadata to reset itself |
323 | | mdata->all_music->resync(); |
324 | | mdata->all_playlists->postLoad(); |
| 394 | RebuildMusicTree(mdata); |
325 | 395 | } |
326 | 396 | } |
327 | 397 | else if (sel == "settings_scan") |
… |
… |
|
329 | 399 | if ("" != mdata->startdir) |
330 | 400 | { |
331 | 401 | SearchDir(mdata->startdir); |
332 | | mdata->all_music->resync(); |
333 | | mdata->all_playlists->postLoad(); |
| 402 | RebuildMusicTree(mdata); |
334 | 403 | } |
335 | 404 | } |
336 | 405 | else if (sel == "music_set_general") |
… |
… |
|
602 | 671 | // if startRipper returns true, then new files should be present |
603 | 672 | // so we should look for them. |
604 | 673 | SearchDir(mdata.startdir); |
605 | | mdata.all_music->resync(); |
606 | | mdata.all_playlists->postLoad(); |
| 674 | RebuildMusicTree(&mdata); |
607 | 675 | } |
608 | 676 | postMusic(&mdata); |
609 | 677 | } |
diff -ru ../123/mythplugins/mythmusic/mythmusic/metadata.cpp mythplugins/mythmusic/mythmusic/metadata.cpp
old
|
new
|
|
1 | 1 | #include <iostream> |
| 2 | #include <qapplication.h> |
2 | 3 | #include <qregexp.h> |
3 | 4 | #include <qdatetime.h> |
4 | 5 | #include <qdir.h> |
… |
… |
|
194 | 195 | return; |
195 | 196 | |
196 | 197 | query.prepare("INSERT INTO musicmetadata (artist,compilation_artist,album,title," |
197 | | "genre,year,tracknum,length,filename,compilation,date_added) VALUES " |
| 198 | "genre,year,tracknum,length,filename,compilation,date_added," |
| 199 | "date_modified) VALUES " |
198 | 200 | "(:ARTIST, :COMPILATION_ARTIST, :ALBUM, :TITLE, :GENRE, :YEAR, :TRACKNUM, " |
199 | | ":LENGTH, :FILENAME, :COMPILATION, :DATE_ADDED );"); |
| 201 | ":LENGTH, :FILENAME, :COMPILATION, :DATE_ADDED, :DATE_MODIFIED );"); |
200 | 202 | query.bindValue(":ARTIST", artist.utf8()); |
201 | 203 | query.bindValue(":COMPILATION_ARTIST", compilation_artist.utf8()); |
202 | 204 | query.bindValue(":ALBUM", album.utf8()); |
… |
… |
|
207 | 209 | query.bindValue(":LENGTH", length); |
208 | 210 | query.bindValue(":FILENAME", sqlfilename.utf8()); |
209 | 211 | query.bindValue(":COMPILATION", compilation); |
210 | | query.bindValue(":DATE_ADDED", QDate::currentDate()); |
| 212 | query.bindValue(":DATE_ADDED", QDateTime::currentDateTime()); |
| 213 | query.bindValue(":DATE_MODIFIED", QDateTime::currentDateTime()); |
211 | 214 | |
212 | 215 | query.exec(); |
213 | 216 | |
… |
… |
|
364 | 367 | "compilation_artist = :COMPILATION_ARTIST, " |
365 | 368 | "title = :TITLE, genre = :GENRE, year = :YEAR, " |
366 | 369 | "tracknum = :TRACKNUM, rating = :RATING, " |
367 | | "compilation = :COMPILATION " |
| 370 | "compilation = :COMPILATION, " |
| 371 | "date_modified= :DATE_MODIFIED " |
368 | 372 | "WHERE intid = :ID;"); |
369 | 373 | query.bindValue(":ARTIST", artist.utf8()); |
370 | 374 | query.bindValue(":COMPILATION_ARTIST", compilation_artist.utf8()); |
… |
… |
|
375 | 379 | query.bindValue(":TRACKNUM", tracknum); |
376 | 380 | query.bindValue(":RATING", rating); |
377 | 381 | query.bindValue(":COMPILATION", compilation); |
| 382 | query.bindValue(":DATE_MODIFIED", QDateTime::currentDateTime()); |
378 | 383 | query.bindValue(":ID", id); |
379 | 384 | |
380 | 385 | if (!query.exec()) |
… |
… |
|
683 | 688 | // loading and sorting |
684 | 689 | // |
685 | 690 | |
686 | | metadata_loader = new MetadataLoadingThread(this); |
687 | | metadata_loader->start(); |
| 691 | metadata_loader = NULL; |
| 692 | startLoading (); |
688 | 693 | |
689 | 694 | all_music.setAutoDelete(true); |
690 | 695 | top_nodes.setAutoDelete(true); |
… |
… |
|
718 | 723 | return false; |
719 | 724 | } |
720 | 725 | |
| 726 | bool AllMusic::startLoading () { |
| 727 | // Set this to false early rather than letting it be delayed till |
| 728 | // the thread calls resync. |
| 729 | done_loading = false; |
| 730 | |
| 731 | if (metadata_loader) { |
| 732 | cleanOutThreads (); |
| 733 | delete metadata_loader; |
| 734 | } |
| 735 | |
| 736 | metadata_loader = new MetadataLoadingThread(this); |
| 737 | metadata_loader->start (); |
| 738 | |
| 739 | return true; |
| 740 | } |
| 741 | |
721 | 742 | void AllMusic::resync() |
722 | 743 | { |
723 | 744 | done_loading = false; |
… |
… |
|
1161 | 1182 | if( *it != "genre" && |
1162 | 1183 | *it != "artist" && |
1163 | 1184 | *it != "splitartist" && |
| 1185 | *it != "splitartist1" && |
1164 | 1186 | *it != "album" && |
1165 | 1187 | *it != "title") |
1166 | 1188 | { |
diff -ru ../123/mythplugins/mythmusic/mythmusic/metadata.h mythplugins/mythmusic/mythmusic/metadata.h
old
|
new
|
|
274 | 274 | Metadata* getMetadata(int an_id); |
275 | 275 | bool updateMetadata(int an_id, Metadata *the_track); |
276 | 276 | void save(); |
| 277 | /** \brief Start loading metadata. |
| 278 | Makes the AllMusic object run it's resync in a thread. Once done, it's |
| 279 | doneLoading method will return true. |
| 280 | |
| 281 | \note Alternatively, it could be made to emit a signal so the |
| 282 | caller won't have to poll for completion. |
| 283 | |
| 284 | \returns true if the loader thread was started |
| 285 | */ |
| 286 | bool startLoading (); |
277 | 287 | void resync(); // After a CD rip, for example |
278 | 288 | void clearCDData(); |
279 | 289 | void addCDTrack(Metadata *the_track); |