|
MythTV
0.26-pre
|
00001 // qt 00002 #include <QApplication> 00003 #include <QRegExp> 00004 #include <QDateTime> 00005 #include <QDir> 00006 00007 // mythtv 00008 #include <mythcontext.h> 00009 #include <mythwidgets.h> 00010 #include <mythdb.h> 00011 #include <mythdirs.h> 00012 #include <mythprogressdialog.h> 00013 #include <mythdownloadmanager.h> 00014 #include <mythlogging.h> 00015 #include <mythmiscutil.h> 00016 00017 // mythmusic 00018 #include "metadata.h" 00019 #include "metaio.h" 00020 #include "metaioid3.h" 00021 #include "metaiomp4.h" 00022 #include "metaioavfcomment.h" 00023 #include "metaiooggvorbis.h" 00024 #include "metaioflacvorbis.h" 00025 #include "metaiowavpack.h" 00026 #include "playlist.h" 00027 #include "playlistcontainer.h" 00028 #include "musicutils.h" 00029 00030 00031 00032 // this is the global MusicData object shared thoughout MythMusic 00033 MusicData *gMusicData = NULL; 00034 00035 static QString thePrefix = "the "; 00036 00037 bool operator==(const Metadata& a, const Metadata& b) 00038 { 00039 if (a.Filename() == b.Filename()) 00040 return true; 00041 return false; 00042 } 00043 00044 bool operator!=(const Metadata& a, const Metadata& b) 00045 { 00046 if (a.Filename() != b.Filename()) 00047 return true; 00048 return false; 00049 } 00050 00051 Metadata::~Metadata() 00052 { 00053 if (m_albumArt) 00054 { 00055 delete m_albumArt; 00056 m_albumArt = NULL; 00057 } 00058 } 00059 00060 00061 Metadata& Metadata::operator=(const Metadata &rhs) 00062 { 00063 m_artist = rhs.m_artist; 00064 m_compilation_artist = rhs.m_compilation_artist; 00065 m_album = rhs.m_album; 00066 m_title = rhs.m_title; 00067 m_formattedartist = rhs.m_formattedartist; 00068 m_formattedtitle = rhs.m_formattedtitle; 00069 m_genre = rhs.m_genre; 00070 m_year = rhs.m_year; 00071 m_tracknum = rhs.m_tracknum; 00072 m_trackCount = rhs.m_trackCount; 00073 m_length = rhs.m_length; 00074 m_rating = rhs.m_rating; 00075 m_lastplay = rhs.m_lastplay; 00076 m_templastplay = rhs.m_templastplay; 00077 m_dateadded = rhs.m_dateadded; 00078 m_playcount = rhs.m_playcount; 00079 m_tempplaycount = rhs.m_tempplaycount; 00080 m_compilation = rhs.m_compilation; 00081 m_id = rhs.m_id; 00082 m_filename = rhs.m_filename; 00083 m_directoryid = rhs.m_directoryid; 00084 m_artistid = rhs.m_artistid; 00085 m_compartistid = rhs.m_compartistid; 00086 m_albumid = rhs.m_albumid; 00087 m_genreid = rhs.m_genreid; 00088 m_albumArt = NULL; 00089 m_format = rhs.m_format; 00090 m_changed = rhs.m_changed; 00091 00092 return *this; 00093 } 00094 00095 void Metadata::persist() 00096 { 00097 if (m_id < 1) 00098 return; 00099 00100 if (m_templastplay.isValid()) 00101 { 00102 m_lastplay = m_templastplay; 00103 m_playcount = m_tempplaycount; 00104 00105 m_templastplay = QDateTime(); 00106 } 00107 00108 MSqlQuery query(MSqlQuery::InitCon()); 00109 query.prepare("UPDATE music_songs set rating = :RATING , " 00110 "numplays = :PLAYCOUNT , lastplay = :LASTPLAY " 00111 "where song_id = :ID ;"); 00112 query.bindValue(":RATING", m_rating); 00113 query.bindValue(":PLAYCOUNT", m_playcount); 00114 query.bindValue(":LASTPLAY", m_lastplay); 00115 query.bindValue(":ID", m_id); 00116 00117 if (!query.exec()) 00118 MythDB::DBError("music persist", query); 00119 00120 gPlayer->sendTrackStatsChangedEvent(ID()); 00121 00122 m_changed = false; 00123 } 00124 00125 00126 void Metadata::UpdateModTime() const 00127 { 00128 if (m_id < 1) 00129 return; 00130 00131 MSqlQuery query(MSqlQuery::InitCon()); 00132 00133 query.prepare("UPDATE music_songs SET date_modified = :DATE_MOD " 00134 "WHERE song_id= :ID ;"); 00135 00136 query.bindValue(":DATE_MOD", QDateTime::currentDateTime()); 00137 query.bindValue(":ID", m_id); 00138 00139 if (!query.exec()) 00140 MythDB::DBError("Metadata::UpdateModTime", 00141 query); 00142 } 00143 00144 int Metadata::compare(const Metadata *other) const 00145 { 00146 if (m_format == "cast") 00147 { 00148 int artist_cmp = Artist().toLower().localeAwareCompare( 00149 other->Artist().toLower()); 00150 00151 if (artist_cmp == 0) 00152 return Title().toLower().localeAwareCompare( 00153 other->Title().toLower()); 00154 00155 return artist_cmp; 00156 } 00157 else 00158 { 00159 int track_cmp = Track() - other->Track(); 00160 00161 if (track_cmp == 0) 00162 return Title().toLower().localeAwareCompare( 00163 other->Title().toLower()); 00164 00165 return track_cmp; 00166 } 00167 } 00168 00169 bool Metadata::isInDatabase() 00170 { 00171 bool retval = false; 00172 00173 QString sqldir = m_filename.section('/', 0, -2); 00174 QString sqlfilename = m_filename.section('/', -1); 00175 00176 MSqlQuery query(MSqlQuery::InitCon()); 00177 query.prepare("SELECT music_artists.artist_name, " 00178 "music_comp_artists.artist_name AS compilation_artist, " 00179 "music_albums.album_name, music_songs.name, music_genres.genre, " 00180 "music_songs.year, music_songs.track, music_songs.length, " 00181 "music_songs.song_id, music_songs.rating, music_songs.numplays, " 00182 "music_songs.lastplay, music_albums.compilation, music_songs.format, " 00183 "music_songs.track_count " 00184 "FROM music_songs " 00185 "LEFT JOIN music_directories " 00186 "ON music_songs.directory_id=music_directories.directory_id " 00187 "LEFT JOIN music_artists ON music_songs.artist_id=music_artists.artist_id " 00188 "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id " 00189 "LEFT JOIN music_artists AS music_comp_artists " 00190 "ON music_albums.artist_id=music_comp_artists.artist_id " 00191 "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id " 00192 "WHERE music_songs.filename = :FILENAME " 00193 "AND music_directories.path = :DIRECTORY ;"); 00194 query.bindValue(":FILENAME", sqlfilename); 00195 query.bindValue(":DIRECTORY", sqldir); 00196 00197 if (query.exec() && query.next()) 00198 { 00199 00200 m_artist = query.value(0).toString(); 00201 m_compilation_artist = query.value(1).toString(); 00202 m_album = query.value(2).toString(); 00203 m_title = query.value(3).toString(); 00204 m_genre = query.value(4).toString(); 00205 m_year = query.value(5).toInt(); 00206 m_tracknum = query.value(6).toInt(); 00207 m_length = query.value(7).toInt(); 00208 m_id = query.value(8).toUInt(); 00209 m_rating = query.value(9).toInt(); 00210 m_playcount = query.value(10).toInt(); 00211 m_lastplay = query.value(11).toDateTime(); 00212 m_compilation = (query.value(12).toInt() > 0); 00213 m_format = query.value(13).toString(); 00214 m_trackCount = query.value(14).toInt(); 00215 00216 retval = true; 00217 } 00218 00219 return retval; 00220 } 00221 00222 void Metadata::dumpToDatabase() 00223 { 00224 QString sqldir = m_filename.section('/', 0, -2); 00225 QString sqlfilename = m_filename.section('/', -1); 00226 00227 checkEmptyFields(); 00228 00229 MSqlQuery query(MSqlQuery::InitCon()); 00230 00231 if (sqldir.isEmpty()) 00232 { 00233 m_directoryid = 0; 00234 } 00235 else if (m_directoryid < 0) 00236 { 00237 // Load the directory id 00238 query.prepare("SELECT directory_id FROM music_directories " 00239 "WHERE path = :DIRECTORY ;"); 00240 query.bindValue(":DIRECTORY", sqldir); 00241 00242 if (!query.exec() || !query.isActive()) 00243 { 00244 MythDB::DBError("music select directory id", query); 00245 return; 00246 } 00247 if (query.next()) 00248 { 00249 m_directoryid = query.value(0).toInt(); 00250 } 00251 else 00252 { 00253 query.prepare("INSERT INTO music_directories (path) VALUES (:DIRECTORY);"); 00254 query.bindValue(":DIRECTORY", sqldir); 00255 00256 if (!query.exec() || !query.isActive() || query.numRowsAffected() <= 0) 00257 { 00258 MythDB::DBError("music insert directory", query); 00259 return; 00260 } 00261 m_directoryid = query.lastInsertId().toInt(); 00262 } 00263 } 00264 00265 if (m_artistid < 0) 00266 { 00267 // Load the artist id 00268 query.prepare("SELECT artist_id FROM music_artists " 00269 "WHERE artist_name = :ARTIST ;"); 00270 query.bindValue(":ARTIST", m_artist); 00271 00272 if (!query.exec() || !query.isActive()) 00273 { 00274 MythDB::DBError("music select artist id", query); 00275 return; 00276 } 00277 if (query.next()) 00278 { 00279 m_artistid = query.value(0).toInt(); 00280 } 00281 else 00282 { 00283 query.prepare("INSERT INTO music_artists (artist_name) VALUES (:ARTIST);"); 00284 query.bindValue(":ARTIST", m_artist); 00285 00286 if (!query.exec() || !query.isActive() || query.numRowsAffected() <= 0) 00287 { 00288 MythDB::DBError("music insert artist", query); 00289 return; 00290 } 00291 m_artistid = query.lastInsertId().toInt(); 00292 } 00293 } 00294 00295 // Compilation Artist 00296 if (m_artist == m_compilation_artist) 00297 { 00298 m_compartistid = m_artistid; 00299 } 00300 else 00301 { 00302 query.prepare("SELECT artist_id FROM music_artists " 00303 "WHERE artist_name = :ARTIST ;"); 00304 query.bindValue(":ARTIST", m_compilation_artist); 00305 if (!query.exec() || !query.isActive()) 00306 { 00307 MythDB::DBError("music select compilation artist id", query); 00308 return; 00309 } 00310 if (query.next()) 00311 { 00312 m_compartistid = query.value(0).toInt(); 00313 } 00314 else 00315 { 00316 query.prepare("INSERT INTO music_artists (artist_name) VALUES (:ARTIST);"); 00317 query.bindValue(":ARTIST", m_compilation_artist); 00318 00319 if (!query.exec() || !query.isActive() || query.numRowsAffected() <= 0) 00320 { 00321 MythDB::DBError("music insert compilation artist", query); 00322 return; 00323 } 00324 m_compartistid = query.lastInsertId().toInt(); 00325 } 00326 } 00327 00328 // Album 00329 if (m_albumid < 0) 00330 { 00331 query.prepare("SELECT album_id FROM music_albums " 00332 "WHERE artist_id = :COMP_ARTIST_ID " 00333 " AND album_name = :ALBUM ;"); 00334 query.bindValue(":COMP_ARTIST_ID", m_compartistid); 00335 query.bindValue(":ALBUM", m_album); 00336 if (!query.exec() || !query.isActive()) 00337 { 00338 MythDB::DBError("music select album id", query); 00339 return; 00340 } 00341 if (query.next()) 00342 { 00343 m_albumid = query.value(0).toInt(); 00344 } 00345 else 00346 { 00347 query.prepare("INSERT INTO music_albums (artist_id, album_name, compilation, year) VALUES (:COMP_ARTIST_ID, :ALBUM, :COMPILATION, :YEAR);"); 00348 query.bindValue(":COMP_ARTIST_ID", m_compartistid); 00349 query.bindValue(":ALBUM", m_album); 00350 query.bindValue(":COMPILATION", m_compilation); 00351 query.bindValue(":YEAR", m_year); 00352 00353 if (!query.exec() || !query.isActive() || query.numRowsAffected() <= 0) 00354 { 00355 MythDB::DBError("music insert album", query); 00356 return; 00357 } 00358 m_albumid = query.lastInsertId().toInt(); 00359 } 00360 } 00361 00362 if (m_genreid < 0) 00363 { 00364 // Genres 00365 query.prepare("SELECT genre_id FROM music_genres " 00366 "WHERE genre = :GENRE ;"); 00367 query.bindValue(":GENRE", m_genre); 00368 if (!query.exec() || !query.isActive()) 00369 { 00370 MythDB::DBError("music select genre id", query); 00371 return; 00372 } 00373 if (query.next()) 00374 { 00375 m_genreid = query.value(0).toInt(); 00376 } 00377 else 00378 { 00379 query.prepare("INSERT INTO music_genres (genre) VALUES (:GENRE);"); 00380 query.bindValue(":GENRE", m_genre); 00381 00382 if (!query.exec() || !query.isActive() || query.numRowsAffected() <= 0) 00383 { 00384 MythDB::DBError("music insert genre", query); 00385 return; 00386 } 00387 m_genreid = query.lastInsertId().toInt(); 00388 } 00389 } 00390 00391 // We have all the id's now. We can insert it. 00392 QString strQuery; 00393 if (m_id < 1) 00394 { 00395 strQuery = "INSERT INTO music_songs ( directory_id," 00396 " artist_id, album_id, name, genre_id," 00397 " year, track, length, filename," 00398 " rating, format, date_entered, date_modified," 00399 " numplays, track_count) " 00400 "VALUES ( " 00401 " :DIRECTORY, " 00402 " :ARTIST, :ALBUM, :TITLE, :GENRE," 00403 " :YEAR, :TRACKNUM, :LENGTH, :FILENAME," 00404 " :RATING, :FORMAT, :DATE_ADD, :DATE_MOD," 00405 " :PLAYCOUNT,:TRACKCOUNT );"; 00406 } 00407 else 00408 { 00409 strQuery = "UPDATE music_songs SET" 00410 " directory_id = :DIRECTORY" 00411 ", artist_id = :ARTIST" 00412 ", album_id = :ALBUM" 00413 ", name = :TITLE" 00414 ", genre_id = :GENRE" 00415 ", year = :YEAR" 00416 ", track = :TRACKNUM" 00417 ", length = :LENGTH" 00418 ", filename = :FILENAME" 00419 ", rating = :RATING" 00420 ", format = :FORMAT" 00421 ", date_modified = :DATE_MOD " 00422 ", numplays = :PLAYCOUNT " 00423 ", track_count = :TRACKCOUNT " 00424 "WHERE song_id= :ID ;"; 00425 } 00426 00427 query.prepare(strQuery); 00428 00429 query.bindValue(":DIRECTORY", m_directoryid); 00430 query.bindValue(":ARTIST", m_artistid); 00431 query.bindValue(":ALBUM", m_albumid); 00432 query.bindValue(":TITLE", m_title); 00433 query.bindValue(":GENRE", m_genreid); 00434 query.bindValue(":YEAR", m_year); 00435 query.bindValue(":TRACKNUM", m_tracknum); 00436 query.bindValue(":LENGTH", m_length); 00437 query.bindValue(":FILENAME", sqlfilename); 00438 query.bindValue(":RATING", m_rating); 00439 query.bindValue(":FORMAT", m_format); 00440 query.bindValue(":DATE_MOD", QDateTime::currentDateTime()); 00441 query.bindValue(":PLAYCOUNT", m_playcount); 00442 00443 if (m_id < 1) 00444 query.bindValue(":DATE_ADD", QDateTime::currentDateTime()); 00445 else 00446 query.bindValue(":ID", m_id); 00447 00448 query.bindValue(":TRACKCOUNT", m_trackCount); 00449 00450 if (!query.exec()) 00451 MythDB::DBError("Metadata::dumpToDatabase - updating music_songs", 00452 query); 00453 00454 if (m_id < 1 && query.isActive() && 1 == query.numRowsAffected()) 00455 m_id = query.lastInsertId().toInt(); 00456 00457 // save the albumart to the db 00458 if (m_albumArt) 00459 m_albumArt->dumpToDatabase(); 00460 00461 // make sure the compilation flag is updated 00462 query.prepare("UPDATE music_albums SET compilation = :COMPILATION, year = :YEAR " 00463 "WHERE music_albums.album_id = :ALBUMID"); 00464 query.bindValue(":ALBUMID", m_albumid); 00465 query.bindValue(":COMPILATION", m_compilation); 00466 query.bindValue(":YEAR", m_year); 00467 00468 if (!query.exec() || !query.isActive()) 00469 { 00470 MythDB::DBError("music compilation update", query); 00471 return; 00472 } 00473 } 00474 00475 // Default values for formats 00476 // NB These will eventually be customizable.... 00477 QString Metadata::m_formatnormalfileartist = "ARTIST"; 00478 QString Metadata::m_formatnormalfiletrack = "TITLE"; 00479 QString Metadata::m_formatnormalcdartist = "ARTIST"; 00480 QString Metadata::m_formatnormalcdtrack = "TITLE"; 00481 QString Metadata::m_formatcompilationfileartist = "COMPARTIST"; 00482 QString Metadata::m_formatcompilationfiletrack = "TITLE (ARTIST)"; 00483 QString Metadata::m_formatcompilationcdartist = "COMPARTIST"; 00484 QString Metadata::m_formatcompilationcdtrack = "TITLE (ARTIST)"; 00485 00486 void Metadata::setArtistAndTrackFormats() 00487 { 00488 QString tmp; 00489 00490 tmp = gCoreContext->GetSetting("MusicFormatNormalFileArtist"); 00491 if (!tmp.isEmpty()) 00492 m_formatnormalfileartist = tmp; 00493 00494 tmp = gCoreContext->GetSetting("MusicFormatNormalFileTrack"); 00495 if (!tmp.isEmpty()) 00496 m_formatnormalfiletrack = tmp; 00497 00498 tmp = gCoreContext->GetSetting("MusicFormatNormalCDArtist"); 00499 if (!tmp.isEmpty()) 00500 m_formatnormalcdartist = tmp; 00501 00502 tmp = gCoreContext->GetSetting("MusicFormatNormalCDTrack"); 00503 if (!tmp.isEmpty()) 00504 m_formatnormalcdtrack = tmp; 00505 00506 tmp = gCoreContext->GetSetting("MusicFormatCompilationFileArtist"); 00507 if (!tmp.isEmpty()) 00508 m_formatcompilationfileartist = tmp; 00509 00510 tmp = gCoreContext->GetSetting("MusicFormatCompilationFileTrack"); 00511 if (!tmp.isEmpty()) 00512 m_formatcompilationfiletrack = tmp; 00513 00514 tmp = gCoreContext->GetSetting("MusicFormatCompilationCDArtist"); 00515 if (!tmp.isEmpty()) 00516 m_formatcompilationcdartist = tmp; 00517 00518 tmp = gCoreContext->GetSetting("MusicFormatCompilationCDTrack"); 00519 if (!tmp.isEmpty()) 00520 m_formatcompilationcdtrack = tmp; 00521 } 00522 00523 00524 bool Metadata::determineIfCompilation(bool cd) 00525 { 00526 m_compilation = (!m_compilation_artist.isEmpty() 00527 && m_artist != m_compilation_artist); 00528 setCompilationFormatting(cd); 00529 return m_compilation; 00530 } 00531 00532 00533 inline QString Metadata::formatReplaceSymbols(const QString &format) 00534 { 00535 QString rv = format; 00536 rv.replace("COMPARTIST", m_compilation_artist); 00537 rv.replace("ARTIST", m_artist); 00538 rv.replace("TITLE", m_title); 00539 rv.replace("TRACK", QString("%1").arg(m_tracknum, 2)); 00540 return rv; 00541 } 00542 00543 void Metadata::checkEmptyFields() 00544 { 00545 if (m_artist.isEmpty()) 00546 m_artist = QObject::tr("Unknown Artist"); 00547 // This should be the same as Artist if it's a compilation track or blank 00548 if (!m_compilation || m_compilation_artist.isEmpty()) 00549 m_compilation_artist = m_artist; 00550 if (m_album.isEmpty()) 00551 m_album = QObject::tr("Unknown Album"); 00552 if (m_title.isEmpty()) 00553 m_title = m_filename; 00554 if (m_genre.isEmpty()) 00555 m_genre = QObject::tr("Unknown Genre"); 00556 00557 } 00558 00559 inline void Metadata::setCompilationFormatting(bool cd) 00560 { 00561 QString format_artist, format_title; 00562 00563 if (!m_compilation 00564 || "" == m_compilation_artist 00565 || m_artist == m_compilation_artist) 00566 { 00567 if (!cd) 00568 { 00569 format_artist = m_formatnormalfileartist; 00570 format_title = m_formatnormalfiletrack; 00571 } 00572 else 00573 { 00574 format_artist = m_formatnormalcdartist; 00575 format_title = m_formatnormalcdtrack; 00576 } 00577 } 00578 else 00579 { 00580 if (!cd) 00581 { 00582 format_artist = m_formatcompilationfileartist; 00583 format_title = m_formatcompilationfiletrack; 00584 } 00585 else 00586 { 00587 format_artist = m_formatcompilationcdartist; 00588 format_title = m_formatcompilationcdtrack; 00589 } 00590 } 00591 00592 // NB Could do some comparisons here to save memory with shallow copies... 00593 m_formattedartist = formatReplaceSymbols(format_artist); 00594 m_formattedtitle = formatReplaceSymbols(format_title); 00595 } 00596 00597 00598 QString Metadata::FormatArtist() 00599 { 00600 if (m_formattedartist.isEmpty()) 00601 setCompilationFormatting(); 00602 00603 return m_formattedartist; 00604 } 00605 00606 00607 QString Metadata::FormatTitle() 00608 { 00609 if (m_formattedtitle.isEmpty()) 00610 setCompilationFormatting(); 00611 00612 return m_formattedtitle; 00613 } 00614 00615 QString Metadata::Filename(bool find) const 00616 { 00617 // if not asked to find the file just return the raw filename from the DB 00618 if (find == false) 00619 return m_filename; 00620 00621 // check for a cd track 00622 if (m_filename.endsWith(".cda")) 00623 return m_filename; 00624 00625 // check for http urls etc 00626 if (m_filename.contains("://")) 00627 return m_filename; 00628 00629 // first check to see if the filename is complete 00630 if (QFile::exists(m_filename)) 00631 return m_filename; 00632 00633 // next try appending the start directory 00634 if (QFile::exists(gMusicData->musicDir + m_filename)) 00635 return gMusicData->musicDir + m_filename; 00636 00637 // maybe it's in our 'Music' storage group 00638 //TODO add storage group lookup here 00639 00640 // not found 00641 LOG(VB_GENERAL, LOG_ERR, QString("Metadata: Asked to get the filename for a track but no file found: %1") 00642 .arg(m_filename)); 00643 return QString(); 00644 } 00645 00646 void Metadata::setField(const QString &field, const QString &data) 00647 { 00648 if (field == "artist") 00649 m_artist = data; 00650 else if (field == "compilation_artist") 00651 m_compilation_artist = data; 00652 else if (field == "album") 00653 m_album = data; 00654 else if (field == "title") 00655 m_title = data; 00656 else if (field == "genre") 00657 m_genre = data; 00658 else if (field == "filename") 00659 m_filename = data; 00660 else if (field == "year") 00661 m_year = data.toInt(); 00662 else if (field == "tracknum") 00663 m_tracknum = data.toInt(); 00664 else if (field == "trackcount") 00665 m_trackCount = data.toInt(); 00666 else if (field == "length") 00667 m_length = data.toInt(); 00668 else if (field == "compilation") 00669 m_compilation = (data.toInt() > 0); 00670 00671 else 00672 { 00673 LOG(VB_GENERAL, LOG_ERR, QString("Something asked me to set data " 00674 "for a field called %1").arg(field)); 00675 } 00676 } 00677 00678 void Metadata::getField(const QString &field, QString *data) 00679 { 00680 if (field == "artist") 00681 *data = FormatArtist(); 00682 else if (field == "album") 00683 *data = m_album; 00684 else if (field == "title") 00685 *data = FormatTitle(); 00686 else if (field == "genre") 00687 *data = m_genre; 00688 else 00689 { 00690 LOG(VB_GENERAL, LOG_ERR, QString("Something asked me to return data " 00691 "about a field called %1").arg(field)); 00692 *data = "I Dunno"; 00693 } 00694 } 00695 00696 void Metadata::toMap(MetadataMap &metadataMap, const QString &prefix) 00697 { 00698 metadataMap[prefix + "artist"] = m_artist; 00699 metadataMap[prefix + "formatartist"] = FormatArtist(); 00700 metadataMap[prefix + "compilationartist"] = m_compilation_artist; 00701 metadataMap[prefix + "album"] = m_album; 00702 metadataMap[prefix + "title"] = m_title; 00703 metadataMap[prefix + "formattitle"] = FormatTitle(); 00704 metadataMap[prefix + "tracknum"] = (m_tracknum > 0 ? QString("%1").arg(m_tracknum) : ""); 00705 metadataMap[prefix + "trackcount"] = (m_trackCount > 0 ? QString("%1").arg(m_trackCount) : ""); 00706 metadataMap[prefix + "genre"] = m_genre; 00707 metadataMap[prefix + "year"] = (m_year > 0 ? QString("%1").arg(m_year) : ""); 00708 00709 int len = m_length / 1000; 00710 int eh = len / 3600; 00711 int em = (len / 60) % 60; 00712 int es = len % 60; 00713 if (eh > 0) 00714 metadataMap[prefix + "length"] = QString().sprintf("%d:%02d:%02d", eh, em, es); 00715 else 00716 metadataMap[prefix + "length"] = QString().sprintf("%02d:%02d", em, es); 00717 00718 if (m_lastplay.isValid()) 00719 metadataMap[prefix + "lastplayed"] = MythDateTimeToString(m_lastplay, 00720 kDateFull | kSimplify | kAddYear); 00721 else 00722 metadataMap[prefix + "lastplayed"] = QObject::tr("Never Played"); 00723 00724 metadataMap[prefix + "dateadded"] = MythDateTimeToString(m_dateadded, 00725 kDateFull | kSimplify | kAddYear); 00726 00727 metadataMap[prefix + "playcount"] = QString::number(m_playcount); 00728 // FIXME we should use Filename() here but that will slow things down because of the hunt for the file 00729 metadataMap[prefix + "filename"] = gMusicData->musicDir + m_filename; 00730 } 00731 00732 void Metadata::decRating() 00733 { 00734 if (m_rating > 0) 00735 { 00736 m_rating--; 00737 } 00738 m_changed = true; 00739 } 00740 00741 void Metadata::incRating() 00742 { 00743 if (m_rating < 10) 00744 { 00745 m_rating++; 00746 } 00747 m_changed = true; 00748 } 00749 00750 void Metadata::setLastPlay() 00751 { 00752 m_templastplay = QDateTime::currentDateTime(); 00753 m_changed = true; 00754 } 00755 00756 void Metadata::incPlayCount() 00757 { 00758 m_tempplaycount = m_playcount + 1; 00759 m_changed = true; 00760 } 00761 00762 void Metadata::setEmbeddedAlbumArt(AlbumArtList &albumart) 00763 { 00764 // add the images found in the tag to the ones we got from the DB 00765 00766 if (!m_albumArt) 00767 m_albumArt = new AlbumArtImages(this); 00768 00769 for (int x = 0; x < albumart.size(); x++) 00770 { 00771 m_albumArt->addImage(albumart.at(x)); 00772 } 00773 00774 m_changed = true; 00775 } 00776 00777 QStringList Metadata::fillFieldList(QString field) 00778 { 00779 QStringList searchList; 00780 searchList.clear(); 00781 00782 MSqlQuery query(MSqlQuery::InitCon()); 00783 if ("artist" == field) 00784 { 00785 query.prepare("SELECT artist_name FROM music_artists ORDER BY artist_name;"); 00786 } 00787 else if ("compilation_artist" == field) 00788 { 00789 query.prepare("SELECT DISTINCT artist_name FROM music_artists, music_albums where " 00790 "music_albums.artist_id=music_artists.artist_id ORDER BY artist_name"); 00791 } 00792 else if ("album" == field) 00793 { 00794 query.prepare("SELECT album_name FROM music_albums ORDER BY album_name;"); 00795 } 00796 else if ("title" == field) 00797 { 00798 query.prepare("SELECT name FROM music_songs ORDER BY name;"); 00799 } 00800 else if ("genre" == field) 00801 { 00802 query.prepare("SELECT genre FROM music_genres ORDER BY genre;"); 00803 } 00804 else 00805 { 00806 return searchList; 00807 } 00808 00809 if (query.exec() && query.isActive()) 00810 { 00811 while (query.next()) 00812 { 00813 searchList << query.value(0).toString(); 00814 } 00815 } 00816 return searchList; 00817 } 00818 00819 QString Metadata::getAlbumArtFile(void) 00820 { 00821 if (!m_albumArt) 00822 m_albumArt = new AlbumArtImages(this); 00823 00824 AlbumArtImage *albumart_image = NULL; 00825 QString res; 00826 00827 if ((albumart_image = m_albumArt->getImage(IT_FRONTCOVER))) 00828 res = albumart_image->filename; 00829 else if ((albumart_image = m_albumArt->getImage(IT_UNKNOWN))) 00830 res = albumart_image->filename; 00831 else if ((albumart_image = m_albumArt->getImage(IT_BACKCOVER))) 00832 res = albumart_image->filename; 00833 else if ((albumart_image = m_albumArt->getImage(IT_INLAY))) 00834 res = albumart_image->filename; 00835 else if ((albumart_image = m_albumArt->getImage(IT_CD))) 00836 res = albumart_image->filename; 00837 00838 // check file exists 00839 if (!res.isEmpty()) 00840 { 00841 int repo = ID_TO_REPO(m_id); 00842 if (repo == RT_Radio) 00843 { 00844 // image is a radio station icon, check if we have already downloaded and cached it 00845 QString path = GetConfDir() + "/MythMusic/AlbumArt/"; 00846 QFileInfo fi(res); 00847 QString filename = QString("%1-%2.%3").arg(m_id).arg("front").arg(fi.suffix()); 00848 00849 albumart_image->filename = path + filename; 00850 00851 if (!QFile::exists(albumart_image->filename)) 00852 { 00853 // file does not exist so try to download and cache it 00854 if (!GetMythDownloadManager()->download(res, albumart_image->filename)) 00855 { 00856 m_albumArt->getImageList()->removeAll(albumart_image); 00857 return QString(""); 00858 } 00859 } 00860 00861 res = albumart_image->filename; 00862 } 00863 else 00864 { 00865 if (!QFile::exists(res)) 00866 { 00867 if (albumart_image->embedded && getTagger()->supportsEmbeddedImages()) 00868 { 00869 // image is embedded try to extract it from the tag and cache it for latter 00870 QImage *image = getTagger()->getAlbumArt(Filename(), 00871 albumart_image->imageType); 00872 if (image) 00873 { 00874 image->save(res); 00875 delete image; 00876 return res; 00877 } 00878 } 00879 else 00880 { 00881 // image is in a file but couldn't be found! 00882 m_albumArt->getImageList()->removeAll(albumart_image); 00883 return QString(""); 00884 } 00885 } 00886 } 00887 00888 return res; 00889 } 00890 00891 return QString(""); 00892 } 00893 00894 QString Metadata::getAlbumArtFile(ImageType type) 00895 { 00896 if (!m_albumArt) 00897 m_albumArt = new AlbumArtImages(this); 00898 00899 AlbumArtImage *albumart_image = m_albumArt->getImage(type); 00900 if (albumart_image) 00901 return albumart_image->filename; 00902 00903 return QString(""); 00904 } 00905 00906 AlbumArtImages *Metadata::getAlbumArtImages(void) 00907 { 00908 if (!m_albumArt) 00909 m_albumArt = new AlbumArtImages(this); 00910 00911 return m_albumArt; 00912 } 00913 00914 void Metadata::reloadAlbumArtImages(void) 00915 { 00916 delete m_albumArt; 00917 m_albumArt = NULL; //new AlbumArtImages(this); 00918 } 00919 00920 00922 MetaIO* Metadata::getTagger(void) 00923 { 00924 static MetaIOID3 metaIOID3; 00925 static MetaIOOggVorbis metaIOOggVorbis; 00926 static MetaIOFLACVorbis metaIOFLACVorbis; 00927 static MetaIOMP4 metaIOMP4; 00928 static MetaIOWavPack metaIOWavPack; 00929 static MetaIOAVFComment metaIOAVFComment; 00930 00931 QFileInfo fi(m_filename); 00932 QString extension = fi.suffix(); 00933 00934 if (extension == "mp3" || extension == "mp2") 00935 return &metaIOID3; 00936 else if (extension == "ogg" || extension == "oga") 00937 return &metaIOOggVorbis; 00938 else if (extension == "flac") 00939 { 00940 if (metaIOID3.TagExists(Filename(true))) 00941 return &metaIOID3; 00942 else 00943 return &metaIOFLACVorbis; 00944 } 00945 else if (extension == "m4a") 00946 return &metaIOMP4; 00947 else if (extension == "wv") 00948 return &metaIOWavPack; 00949 else 00950 return &metaIOAVFComment; 00951 } 00952 00953 //-------------------------------------------------------------------------- 00954 00955 MetadataLoadingThread::MetadataLoadingThread(AllMusic *parent_ptr) : 00956 MThread("MetadataLoading"), parent(parent_ptr) 00957 { 00958 } 00959 00960 void MetadataLoadingThread::run() 00961 { 00962 RunProlog(); 00963 //if you want to simulate a big music collection load 00964 //sleep(3); 00965 parent->resync(); 00966 RunEpilog(); 00967 } 00968 00969 AllMusic::AllMusic(void) : 00970 m_numPcs(0), 00971 m_numLoaded(0), 00972 m_metadata_loader(NULL), 00973 m_done_loading(false), 00974 m_last_listed(-1), 00975 00976 m_playcountMin(0), 00977 m_playcountMax(0), 00978 m_lastplayMin(0.0), 00979 m_lastplayMax(0.0) 00980 { 00981 // Start a thread to do data loading and sorting 00982 startLoading(); 00983 } 00984 00985 AllMusic::~AllMusic() 00986 { 00987 while (!m_all_music.empty()) 00988 { 00989 delete m_all_music.back(); 00990 m_all_music.pop_back(); 00991 } 00992 00993 while (!m_cdData.empty()) 00994 { 00995 delete m_cdData.back(); 00996 m_cdData.pop_back(); 00997 } 00998 00999 m_metadata_loader->wait(); 01000 delete m_metadata_loader; 01001 } 01002 01003 bool AllMusic::cleanOutThreads() 01004 { 01005 // If this is still running, the user 01006 // probably selected mythmusic and then 01007 // escaped out right away 01008 01009 if (m_metadata_loader->isFinished()) 01010 { 01011 return true; 01012 } 01013 01014 m_metadata_loader->wait(); 01015 return false; 01016 } 01017 01029 bool AllMusic::startLoading(void) 01030 { 01031 // Set this to false early rather than letting it be 01032 // delayed till the thread calls resync. 01033 m_done_loading = false; 01034 01035 if (m_metadata_loader) 01036 { 01037 cleanOutThreads(); 01038 delete m_metadata_loader; 01039 } 01040 01041 m_metadata_loader = new MetadataLoadingThread(this); 01042 m_metadata_loader->start(); 01043 01044 return true; 01045 } 01046 01047 // NOTE we don't clear the existing tracks just load any new ones found in the DB 01048 // maybe we should also check for any removed tracks? 01049 void AllMusic::resync() 01050 { 01051 m_done_loading = false; 01052 01053 QString aquery = "SELECT music_songs.song_id, music_artists.artist_id, music_artists.artist_name, " 01054 "music_comp_artists.artist_name AS compilation_artist, " 01055 "music_albums.album_id, music_albums.album_name, music_songs.name, music_genres.genre, music_songs.year, " 01056 "music_songs.track, music_songs.length, music_songs.directory_id, " 01057 "CONCAT_WS('/', music_directories.path, music_songs.filename) AS filename, " 01058 "music_songs.rating, music_songs.numplays, music_songs.lastplay, music_songs.date_entered, " 01059 "music_albums.compilation, music_songs.format, music_songs.track_count " 01060 "FROM music_songs " 01061 "LEFT JOIN music_directories ON music_songs.directory_id=music_directories.directory_id " 01062 "LEFT JOIN music_artists ON music_songs.artist_id=music_artists.artist_id " 01063 "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id " 01064 "LEFT JOIN music_artists AS music_comp_artists ON music_albums.artist_id=music_comp_artists.artist_id " 01065 "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id " 01066 "ORDER BY music_songs.song_id;"; 01067 01068 QString filename, artist, album, title, compartist; 01069 01070 MSqlQuery query(MSqlQuery::InitCon()); 01071 if (!query.exec(aquery)) 01072 MythDB::DBError("AllMusic::resync", query); 01073 01074 m_numPcs = query.size() * 2; 01075 m_numLoaded = 0; 01076 01077 if (query.isActive() && query.size() > 0) 01078 { 01079 while (query.next()) 01080 { 01081 int id = query.value(0).toInt(); 01082 01083 if (!music_map.contains(id)) 01084 { 01085 filename = query.value(12).toString(); 01086 01087 Metadata *mdata = new Metadata( 01088 filename, 01089 query.value(2).toString(), // artist 01090 query.value(3).toString(), // compilation artist 01091 query.value(5).toString(), // album 01092 query.value(6).toString(), // title 01093 query.value(7).toString(), // genre 01094 query.value(8).toInt(), // year 01095 query.value(9).toInt(), // track no. 01096 query.value(10).toInt(), // length 01097 query.value(0).toInt(), // id 01098 query.value(13).toInt(), // rating 01099 query.value(14).toInt(), // playcount 01100 query.value(15).toDateTime(), // lastplay 01101 query.value(16).toDateTime(), // date_entered 01102 (query.value(17).toInt() > 0), // compilation 01103 query.value(18).toString()); // format 01104 01105 mdata->setDirectoryId(query.value(11).toInt()); 01106 mdata->setArtistId(query.value(1).toInt()); 01107 mdata->setAlbumId(query.value(4).toInt()); 01108 mdata->setTrackCount(query.value(19).toInt()); 01109 01110 // Don't delete mdata, as PtrList now owns it 01111 m_all_music.append(mdata); 01112 01113 music_map[id] = mdata; 01114 } 01115 01116 // compute max/min playcount,lastplay for all music 01117 if (query.at() == 0) 01118 { 01119 // first song 01120 m_playcountMin = m_playcountMax = query.value(13).toInt(); 01121 m_lastplayMin = m_lastplayMax = query.value(14).toDateTime().toTime_t(); 01122 } 01123 else 01124 { 01125 int playCount = query.value(13).toInt(); 01126 double lastPlay = query.value(14).toDateTime().toTime_t(); 01127 01128 m_playcountMin = min(playCount, m_playcountMin); 01129 m_playcountMax = max(playCount, m_playcountMax); 01130 m_lastplayMin = min(lastPlay, m_lastplayMin); 01131 m_lastplayMax = max(lastPlay, m_lastplayMax); 01132 } 01133 m_numLoaded++; 01134 } 01135 } 01136 else 01137 { 01138 LOG(VB_GENERAL, LOG_ERR, "MythMusic hasn't found any tracks! " 01139 "That's ok with me if it's ok with you."); 01140 } 01141 01142 m_done_loading = true; 01143 } 01144 01145 Metadata* AllMusic::getMetadata(int an_id) 01146 { 01147 if (music_map.contains(an_id)) 01148 return music_map[an_id]; 01149 01150 return NULL; 01151 } 01152 01153 bool AllMusic::isValidID(int an_id) 01154 { 01155 return music_map.contains(an_id); 01156 } 01157 01158 bool AllMusic::updateMetadata(int an_id, Metadata *the_track) 01159 { 01160 if (an_id > 0) 01161 { 01162 Metadata *mdata = getMetadata(an_id); 01163 if (mdata) 01164 { 01165 *mdata = *the_track; 01166 return true; 01167 } 01168 } 01169 return false; 01170 } 01171 01173 void AllMusic::save(void) 01174 { 01175 MetadataPtrList::iterator it = m_all_music.begin(); 01176 for (; it != m_all_music.end(); ++it) 01177 { 01178 if ((*it)->hasChanged()) 01179 (*it)->persist(); 01180 } 01181 } 01182 01183 // cd stuff 01184 void AllMusic::clearCDData(void) 01185 { 01186 while (!m_cdData.empty()) 01187 { 01188 delete m_cdData.back(); 01189 m_cdData.pop_back(); 01190 } 01191 01192 m_cdTitle = QObject::tr("CD -- none"); 01193 } 01194 01195 void AllMusic::addCDTrack(const Metadata &the_track) 01196 { 01197 Metadata *mdata = new Metadata(the_track); 01198 mdata->setID(m_cdData.count() + 1); 01199 mdata->setRepo(RT_CD); 01200 m_cdData.append(mdata); 01201 music_map[mdata->ID()] = mdata; 01202 } 01203 01204 bool AllMusic::checkCDTrack(Metadata *the_track) 01205 { 01206 if (m_cdData.count() < 1) 01207 return false; 01208 01209 if (m_cdData.last()->FormatTitle() == the_track->FormatTitle()) 01210 return true; 01211 01212 return false; 01213 } 01214 01215 Metadata* AllMusic::getCDMetadata(int the_track) 01216 { 01217 MetadataPtrList::iterator anit; 01218 for (anit = m_cdData.begin(); anit != m_cdData.end(); ++anit) 01219 { 01220 if ((*anit)->Track() == the_track) 01221 { 01222 return (*anit); 01223 } 01224 } 01225 01226 return NULL; 01227 } 01228 01229 01230 /**************************************************************************/ 01231 01232 AlbumArtImages::AlbumArtImages(Metadata *metadata) 01233 : m_parent(metadata) 01234 { 01235 findImages(); 01236 } 01237 01238 AlbumArtImages::~AlbumArtImages() 01239 { 01240 while (!m_imageList.empty()) 01241 { 01242 delete m_imageList.back(); 01243 m_imageList.pop_back(); 01244 } 01245 } 01246 01247 void AlbumArtImages::findImages(void) 01248 { 01249 while (!m_imageList.empty()) 01250 { 01251 delete m_imageList.back(); 01252 m_imageList.pop_back(); 01253 } 01254 01255 if (m_parent == NULL) 01256 return; 01257 01258 int trackid = ID_TO_ID(m_parent->ID()); 01259 int repo = ID_TO_REPO(m_parent->ID()); 01260 01261 if (repo == RT_Radio) 01262 { 01263 MSqlQuery query(MSqlQuery::InitCon()); 01264 query.prepare("SELECT logourl FROM music_radios WHERE intid = :ID;"); 01265 query.bindValue(":ID", trackid); 01266 if (query.exec()) 01267 { 01268 while (query.next()) 01269 { 01270 QString logoUrl = query.value(0).toString(); 01271 AlbumArtImage *image = new AlbumArtImage(); 01272 image->id = -1; 01273 image->filename = logoUrl; 01274 image->imageType = IT_FRONTCOVER; 01275 image->embedded = false; 01276 01277 m_imageList.push_back(image); 01278 } 01279 } 01280 } 01281 else 01282 { 01283 if (trackid == 0) 01284 return; 01285 01286 QFileInfo fi(m_parent->Filename(false)); 01287 QString dir = fi.path(); 01288 01289 MSqlQuery query(MSqlQuery::InitCon()); 01290 query.prepare("SELECT albumart_id, CONCAT_WS('/', music_directories.path, " 01291 "music_albumart.filename), music_albumart.filename, music_albumart.imagetype, " 01292 "music_albumart.embedded " 01293 "FROM music_albumart " 01294 "LEFT JOIN music_directories ON " 01295 "music_directories.directory_id = music_albumart.directory_id " 01296 "WHERE music_directories.path = :DIR " 01297 "OR song_id = :SONGID " 01298 "ORDER BY music_albumart.imagetype;"); 01299 query.bindValue(":DIR", dir); 01300 query.bindValue(":SONGID", trackid); 01301 if (query.exec()) 01302 { 01303 while (query.next()) 01304 { 01305 AlbumArtImage *image = new AlbumArtImage(); 01306 bool embedded = (query.value(4).toInt() == 1); 01307 image->id = query.value(0).toInt(); 01308 01309 if (embedded) 01310 image->filename = GetConfDir() + "/MythMusic/AlbumArt/" + query.value(1).toString(); 01311 else 01312 image->filename = gMusicData->musicDir + query.value(1).toString(); 01313 01314 image->imageType = (ImageType) query.value(3).toInt(); 01315 image->embedded = embedded; 01316 01317 m_imageList.push_back(image); 01318 } 01319 } 01320 01321 // add any artist images 01322 QString artist = m_parent->Artist().toLower(); 01323 if (findIcon("artist", artist) != QString()) 01324 { 01325 AlbumArtImage *image = new AlbumArtImage(); 01326 image->id = -1; 01327 image->filename = findIcon("artist", artist); 01328 image->imageType = IT_ARTIST; 01329 image->embedded = false; 01330 01331 m_imageList.push_back(image); 01332 } 01333 } 01334 } 01335 01336 AlbumArtImage *AlbumArtImages::getImage(ImageType type) 01337 { 01338 AlbumArtList::iterator it = m_imageList.begin(); 01339 for (; it != m_imageList.end(); ++it) 01340 { 01341 if ((*it)->imageType == type) 01342 return *it; 01343 } 01344 01345 return NULL; 01346 } 01347 01348 QStringList AlbumArtImages::getImageFilenames(void) const 01349 { 01350 QStringList paths; 01351 01352 AlbumArtList::const_iterator it = m_imageList.begin(); 01353 for (; it != m_imageList.end(); ++it) 01354 paths += (*it)->filename; 01355 01356 return paths; 01357 } 01358 01359 AlbumArtImage *AlbumArtImages::getImageAt(uint index) 01360 { 01361 if (index < (uint)m_imageList.size()) 01362 return m_imageList[index]; 01363 01364 return NULL; 01365 } 01366 01367 // static method to get a translated type name from an ImageType 01368 QString AlbumArtImages::getTypeName(ImageType type) 01369 { 01370 // these const's should match the ImageType enum's 01371 static const char* type_strings[] = { 01372 QT_TR_NOOP("Unknown"), // IT_UNKNOWN 01373 QT_TR_NOOP("Front Cover"), // IT_FRONTCOVER 01374 QT_TR_NOOP("Back Cover"), // IT_BACKCOVER 01375 QT_TR_NOOP("CD"), // IT_CD 01376 QT_TR_NOOP("Inlay"), // IT_INLAY 01377 QT_TR_NOOP("Artist"), // IT_ARTIST 01378 }; 01379 01380 return QCoreApplication::translate("AlbumArtImages", 01381 type_strings[type]); 01382 } 01383 01384 // static method to get a filename from an ImageType 01385 QString AlbumArtImages::getTypeFilename(ImageType type) 01386 { 01387 // these const's should match the ImageType enum's 01388 static const char* filename_strings[] = { 01389 QT_TR_NOOP("unknown"), // IT_UNKNOWN 01390 QT_TR_NOOP("front"), // IT_FRONTCOVER 01391 QT_TR_NOOP("back"), // IT_BACKCOVER 01392 QT_TR_NOOP("cd"), // IT_CD 01393 QT_TR_NOOP("inlay"), // IT_INLAY 01394 QT_TR_NOOP("artist") // IT_ARTIST 01395 }; 01396 01397 return QCoreApplication::translate("AlbumArtImages", 01398 filename_strings[type]); 01399 } 01400 01401 // static method to guess the image type from the filename 01402 ImageType AlbumArtImages::guessImageType(const QString &filename) 01403 { 01404 ImageType type = IT_FRONTCOVER; 01405 01406 if (filename.contains("front", Qt::CaseInsensitive) || 01407 filename.contains(QObject::tr("front"), Qt::CaseInsensitive)) 01408 type = IT_FRONTCOVER; 01409 else if (filename.contains("back", Qt::CaseInsensitive) || 01410 filename.contains(QObject::tr("back"), Qt::CaseInsensitive)) 01411 type = IT_BACKCOVER; 01412 else if (filename.contains("inlay", Qt::CaseInsensitive) || 01413 filename.contains(QObject::tr("inlay"), Qt::CaseInsensitive)) 01414 type = IT_INLAY; 01415 else if (filename.contains("cd", Qt::CaseInsensitive) || 01416 filename.contains(QObject::tr("cd"), Qt::CaseInsensitive)) 01417 type = IT_CD; 01418 else if (filename.contains("cover", Qt::CaseInsensitive) || 01419 filename.contains(QObject::tr("cover"), Qt::CaseInsensitive)) 01420 type = IT_FRONTCOVER; 01421 01422 return type; 01423 } 01424 01425 void AlbumArtImages::addImage(const AlbumArtImage &newImage) 01426 { 01427 // do we already have an image of this type? 01428 AlbumArtImage *image = NULL; 01429 01430 AlbumArtList::iterator it = m_imageList.begin(); 01431 for (; it != m_imageList.end(); ++it) 01432 { 01433 if ((*it)->imageType == newImage.imageType && (*it)->embedded == newImage.embedded) 01434 { 01435 image = *it; 01436 break; 01437 } 01438 } 01439 01440 if (!image) 01441 { 01442 // not found so just add it to the list 01443 image = new AlbumArtImage(newImage); 01444 m_imageList.push_back(image); 01445 } 01446 else 01447 { 01448 // we already have an image of this type so just update it with the new info 01449 image->filename = newImage.filename; 01450 image->imageType = newImage.imageType; 01451 image->embedded = newImage.embedded; 01452 image->description = newImage.description; 01453 } 01454 01455 // if this is an embedded image copy it to disc to speed up its display 01456 if (image->embedded && m_parent->getTagger()->supportsEmbeddedImages()) 01457 { 01458 QString path = GetConfDir() + "/MythMusic/AlbumArt/"; 01459 QDir dir(path); 01460 01461 QString filename = QString("%1-%2.jpg").arg(m_parent->ID()).arg(AlbumArtImages::getTypeFilename(image->imageType)); 01462 if (!QFile::exists(path + filename)) 01463 { 01464 if (!dir.exists()) 01465 dir.mkpath(path); 01466 01467 QImage *saveImage = m_parent->getTagger()->getAlbumArt(m_parent->Filename(), image->imageType); 01468 if (saveImage) 01469 { 01470 saveImage->save(path + filename, "JPEG"); 01471 delete saveImage; 01472 } 01473 } 01474 01475 image->filename = path + filename; 01476 } 01477 } 01478 01480 void AlbumArtImages::dumpToDatabase(void) 01481 { 01482 Metadata::IdType trackID = ID_TO_ID(m_parent->ID()); 01483 int directoryID = m_parent->getDirectoryId(); 01484 01485 // sanity check we have a valid songid and directoryid 01486 if (trackID == 0 || directoryID == -1) 01487 { 01488 LOG(VB_GENERAL, LOG_ERR, "AlbumArtImages: Asked to save to the DB but " 01489 "have invalid songid or directoryid"); 01490 return; 01491 } 01492 01493 MSqlQuery query(MSqlQuery::InitCon()); 01494 01495 // remove all albumart for this track from the db 01496 query.prepare("DELETE FROM music_albumart " 01497 "WHERE song_id = :SONGID " 01498 "OR (embedded = 0 AND directory_id = :DIRECTORYID)"); 01499 01500 query.bindValue(":SONGID", trackID); 01501 query.bindValue(":DIRECTORYID", directoryID); 01502 01503 query.exec(); 01504 01505 // now add the albumart to the db 01506 AlbumArtList::iterator it = m_imageList.begin(); 01507 for (; it != m_imageList.end(); ++it) 01508 { 01509 AlbumArtImage *image = (*it); 01510 01511 //TODO: for the moment just ignore artist images 01512 if (image->imageType == IT_ARTIST) 01513 continue; 01514 01515 if (image->id > 0) 01516 { 01517 // re-use the same id this image had before 01518 query.prepare("INSERT INTO music_albumart ( albumart_id, " 01519 "filename, imagetype, song_id, directory_id, embedded ) " 01520 "VALUES ( :ID, :FILENAME, :TYPE, :SONGID, :DIRECTORYID, :EMBED );"); 01521 query.bindValue(":ID", image->id); 01522 } 01523 else 01524 { 01525 query.prepare("INSERT INTO music_albumart ( filename, " 01526 "imagetype, song_id, directory_id, embedded ) VALUES ( " 01527 ":FILENAME, :TYPE, :SONGID, :DIRECTORYID, :EMBED );"); 01528 } 01529 01530 QFileInfo fi(image->filename); 01531 query.bindValue(":FILENAME", fi.fileName()); 01532 01533 query.bindValue(":TYPE", image->imageType); 01534 query.bindValue(":SONGID", image->embedded ? trackID : 0); 01535 query.bindValue(":DIRECTORYID", image->embedded ? 0 : directoryID); 01536 query.bindValue(":EMBED", image->embedded); 01537 01538 if (!query.exec()) 01539 MythDB::DBError("AlbumArtImages::dumpToDatabase - " 01540 "add/update music_albumart", query); 01541 } 01542 } 01543 01544 01545 /**************************************************************************/ 01546 01547 MusicData::MusicData(void) 01548 { 01549 all_playlists = NULL; 01550 all_music = NULL; 01551 initialized = false; 01552 } 01553 01554 MusicData::~MusicData(void) 01555 { 01556 if (all_playlists) 01557 { 01558 delete all_playlists; 01559 all_playlists = NULL; 01560 } 01561 01562 if (all_music) 01563 { 01564 delete all_music; 01565 all_music = NULL; 01566 } 01567 } 01568 01570 void MusicData::reloadMusic(void) 01571 { 01572 if (!all_music || !all_playlists) 01573 return; 01574 01575 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 01576 QString message = QObject::tr("Rebuilding music tree"); 01577 01578 MythUIBusyDialog *busy = new MythUIBusyDialog(message, popupStack, 01579 "musicscanbusydialog"); 01580 01581 if (busy->Create()) 01582 popupStack->AddScreen(busy, false); 01583 else 01584 busy = NULL; 01585 01586 all_music->startLoading(); 01587 while (!all_music->doneLoading()) 01588 { 01589 qApp->processEvents(); 01590 usleep(50000); 01591 } 01592 all_playlists->postLoad(); 01593 01594 if (busy) 01595 busy->Close(); 01596 } 01597
1.7.6.1