00001 #include <iostream>
00002
00003
00004 #include <qapplication.h>
00005 #include <qregexp.h>
00006 #include <qdatetime.h>
00007 #include <qdir.h>
00008
00009 using namespace std;
00010
00011
00012 #include <mythtv/mythcontext.h>
00013 #include <mythtv/mythwidgets.h>
00014 #include <mythtv/mythdbcon.h>
00015
00016
00017 #include "metadata.h"
00018 #include "metaiotaglib.h"
00019 #include "treebuilders.h"
00020 #include "playlist.h"
00021
00022
00023
00024 MusicData *gMusicData = NULL;
00025
00026 static QString thePrefix = "the ";
00027
00028 bool operator==(const Metadata& a, const Metadata& b)
00029 {
00030 if (a.Filename() == b.Filename())
00031 return true;
00032 return false;
00033 }
00034
00035 bool operator!=(const Metadata& a, const Metadata& b)
00036 {
00037 if (a.Filename() != b.Filename())
00038 return true;
00039 return false;
00040 }
00041
00042 Metadata& Metadata::operator=(Metadata *rhs)
00043 {
00044 m_artist = rhs->m_artist;
00045 m_compilation_artist = rhs->m_compilation_artist;
00046 m_album = rhs->m_album;
00047 m_title = rhs->m_title;
00048 m_formattedartist = rhs->m_formattedartist;
00049 m_formattedtitle = rhs->m_formattedtitle;
00050 m_genre = rhs->m_genre;
00051 m_year = rhs->m_year;
00052 m_tracknum = rhs->m_tracknum;
00053 m_length = rhs->m_length;
00054 m_rating = rhs->m_rating;
00055 m_lastplay = rhs->m_lastplay;
00056 m_playcount = rhs->m_playcount;
00057 m_compilation = rhs->m_compilation;
00058 m_id = rhs->m_id;
00059 m_filename = rhs->m_filename;
00060 m_changed = rhs->m_changed;
00061
00062 return *this;
00063 }
00064
00065 QString Metadata::m_startdir = "";
00066
00067 void Metadata::SetStartdir(const QString &dir)
00068 {
00069 Metadata::m_startdir = dir;
00070 }
00071
00072 void Metadata::persist()
00073 {
00074 MSqlQuery query(MSqlQuery::InitCon());
00075 query.prepare("UPDATE music_songs set rating = :RATING , "
00076 "numplays = :PLAYCOUNT , lastplay = :LASTPLAY "
00077 "where song_id = :ID ;");
00078 query.bindValue(":RATING", m_rating);
00079 query.bindValue(":PLAYCOUNT", m_playcount);
00080 query.bindValue(":LASTPLAY", m_lastplay);
00081 query.bindValue(":ID", m_id);
00082
00083 if (!query.exec())
00084 MythContext::DBError("music persist", query);
00085 }
00086
00087 int Metadata::compare(Metadata *other)
00088 {
00089 if (m_format == "cast")
00090 {
00091 int artist_cmp = Artist().lower().localeAwareCompare(other->Artist().lower());
00092
00093 if (artist_cmp == 0)
00094 return Title().lower().localeAwareCompare(other->Title().lower());
00095
00096 return artist_cmp;
00097 }
00098 else
00099 {
00100 int track_cmp = Track() - other->Track();
00101
00102 if (track_cmp == 0)
00103 return Title().lower().localeAwareCompare(other->Title().lower());
00104
00105 return track_cmp;
00106 }
00107 }
00108
00109 bool Metadata::isInDatabase()
00110 {
00111 bool retval = false;
00112
00113 QString sqlfilepath(m_filename);
00114 if (!sqlfilepath.contains("://"))
00115 {
00116 sqlfilepath.remove(0, m_startdir.length());
00117 }
00118 QString sqldir = sqlfilepath.section( '/', 0, -2);
00119 QString sqlfilename =sqlfilepath.section( '/', -1 ) ;
00120
00121 MSqlQuery query(MSqlQuery::InitCon());
00122 query.prepare("SELECT music_artists.artist_name, "
00123 "music_comp_artists.artist_name AS compilation_artist, "
00124 "music_albums.album_name, music_songs.name, music_genres.genre, "
00125 "music_songs.year, music_songs.track, music_songs.length, "
00126 "music_songs.song_id, music_songs.rating, music_songs.numplays, "
00127 "music_songs.lastplay, music_albums.compilation, music_songs.format "
00128 "FROM music_songs "
00129 "LEFT JOIN music_directories "
00130 "ON music_songs.directory_id=music_directories.directory_id "
00131 "LEFT JOIN music_artists ON music_songs.artist_id=music_artists.artist_id "
00132 "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id "
00133 "LEFT JOIN music_artists AS music_comp_artists "
00134 "ON music_albums.artist_id=music_comp_artists.artist_id "
00135 "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id "
00136 "WHERE music_songs.filename = :FILENAME "
00137 "AND music_directories.path = :DIRECTORY ;");
00138 query.bindValue(":FILENAME", sqlfilename.utf8());
00139 query.bindValue(":DIRECTORY", sqldir.utf8());
00140
00141 if (query.exec() && query.isActive() && query.size() > 0)
00142 {
00143 query.next();
00144
00145 m_artist = QString::fromUtf8(query.value(0).toString());
00146 m_compilation_artist = QString::fromUtf8(query.value(1).toString());
00147 m_album = QString::fromUtf8(query.value(2).toString());
00148 m_title = QString::fromUtf8(query.value(3).toString());
00149 m_genre = QString::fromUtf8(query.value(4).toString());
00150 m_year = query.value(5).toInt();
00151 m_tracknum = query.value(6).toInt();
00152 m_length = query.value(7).toInt();
00153 m_id = query.value(8).toUInt();
00154 m_rating = query.value(9).toInt();
00155 m_playcount = query.value(10).toInt();
00156 m_lastplay = query.value(11).toString();
00157 m_compilation = (query.value(12).toInt() > 0);
00158 m_format = query.value(13).toString();
00159
00160 retval = true;
00161 }
00162
00163 return retval;
00164 }
00165
00166 void Metadata::dumpToDatabase()
00167 {
00168 QString sqlfilepath(m_filename);
00169 if (!sqlfilepath.contains("://"))
00170 {
00171 sqlfilepath.remove(0, m_startdir.length());
00172 }
00173 QString sqldir = sqlfilepath.section( '/', 0, -2);
00174 QString sqlfilename = sqlfilepath.section( '/', -1 ) ;
00175
00176 checkEmptyFields();
00177
00178 MSqlQuery query(MSqlQuery::InitCon());
00179
00180 if (sqldir.isEmpty())
00181 {
00182 m_directoryid = 0;
00183 }
00184 else if (m_directoryid < 0)
00185 {
00186
00187 query.prepare("SELECT directory_id FROM music_directories "
00188 "WHERE path = :DIRECTORY ;");
00189 query.bindValue(":DIRECTORY", sqldir.utf8());
00190
00191 if (!query.exec() || !query.isActive())
00192 {
00193 MythContext::DBError("music select directory id", query);
00194 return;
00195 }
00196 if (query.next())
00197 {
00198 m_directoryid = query.value(0).toInt();
00199 }
00200 else
00201 {
00202 query.prepare("INSERT INTO music_directories (path) VALUES (:DIRECTORY);");
00203 query.bindValue(":DIRECTORY", sqldir.utf8());
00204
00205 if (!query.exec() || !query.isActive() || query.numRowsAffected() <= 0)
00206 {
00207 MythContext::DBError("music insert directory", query);
00208 return;
00209 }
00210 m_directoryid = query.lastInsertId().toInt();
00211 }
00212 }
00213
00214 if (m_artistid < 0)
00215 {
00216
00217 query.prepare("SELECT artist_id FROM music_artists "
00218 "WHERE artist_name = :ARTIST ;");
00219 query.bindValue(":ARTIST", m_artist.utf8());
00220
00221 if (!query.exec() || !query.isActive())
00222 {
00223 MythContext::DBError("music select artist id", query);
00224 return;
00225 }
00226 if (query.next())
00227 {
00228 m_artistid = query.value(0).toInt();
00229 }
00230 else
00231 {
00232 query.prepare("INSERT INTO music_artists (artist_name) VALUES (:ARTIST);");
00233 query.bindValue(":ARTIST", m_artist.utf8());
00234
00235 if (!query.exec() || !query.isActive() || query.numRowsAffected() <= 0)
00236 {
00237 MythContext::DBError("music insert artist", query);
00238 return;
00239 }
00240 m_artistid = query.lastInsertId().toInt();
00241 }
00242 }
00243
00244
00245 if (m_artist == m_compilation_artist)
00246 {
00247 m_compartistid = m_artistid;
00248 }
00249 else
00250 {
00251 query.prepare("SELECT artist_id FROM music_artists "
00252 "WHERE artist_name = :ARTIST ;");
00253 query.bindValue(":ARTIST", m_compilation_artist.utf8());
00254 if (!query.exec() || !query.isActive())
00255 {
00256 MythContext::DBError("music select compilation artist id", query);
00257 return;
00258 }
00259 if (query.next())
00260 {
00261 m_compartistid = query.value(0).toInt();
00262 }
00263 else
00264 {
00265 query.prepare("INSERT INTO music_artists (artist_name) VALUES (:ARTIST);");
00266 query.bindValue(":ARTIST", m_compilation_artist.utf8());
00267
00268 if (!query.exec() || !query.isActive() || query.numRowsAffected() <= 0)
00269 {
00270 MythContext::DBError("music insert compilation artist", query);
00271 return;
00272 }
00273 m_compartistid = query.lastInsertId().toInt();
00274 }
00275 }
00276
00277
00278 if (m_albumid < 0)
00279 {
00280 query.prepare("SELECT album_id FROM music_albums "
00281 "WHERE artist_id = :COMP_ARTIST_ID "
00282 " AND album_name = :ALBUM ;");
00283 query.bindValue(":COMP_ARTIST_ID", m_compartistid);
00284 query.bindValue(":ALBUM", m_album.utf8());
00285 if (!query.exec() || !query.isActive())
00286 {
00287 MythContext::DBError("music select album id", query);
00288 return;
00289 }
00290 if (query.next())
00291 {
00292 m_albumid = query.value(0).toInt();
00293 }
00294 else
00295 {
00296 query.prepare("INSERT INTO music_albums (artist_id, album_name, compilation, year) VALUES (:COMP_ARTIST_ID, :ALBUM, :COMPILATION, :YEAR);");
00297 query.bindValue(":COMP_ARTIST_ID", m_compartistid);
00298 query.bindValue(":ALBUM", m_album.utf8());
00299 query.bindValue(":COMPILATION", m_compilation);
00300 query.bindValue(":YEAR", m_year);
00301
00302 if (!query.exec() || !query.isActive() || query.numRowsAffected() <= 0)
00303 {
00304 MythContext::DBError("music insert album", query);
00305 return;
00306 }
00307 m_albumid = query.lastInsertId().toInt();
00308 }
00309 }
00310
00311 if (m_genreid < 0)
00312 {
00313
00314 query.prepare("SELECT genre_id FROM music_genres "
00315 "WHERE genre = :GENRE ;");
00316 query.bindValue(":GENRE", m_genre.utf8());
00317 if (!query.exec() || !query.isActive())
00318 {
00319 MythContext::DBError("music select genre id", query);
00320 return;
00321 }
00322 if (query.next())
00323 {
00324 m_genreid = query.value(0).toInt();
00325 }
00326 else
00327 {
00328 query.prepare("INSERT INTO music_genres (genre) VALUES (:GENRE);");
00329 query.bindValue(":GENRE", m_genre.utf8());
00330
00331 if (!query.exec() || !query.isActive() || query.numRowsAffected() <= 0)
00332 {
00333 MythContext::DBError("music insert genre", query);
00334 return;
00335 }
00336 m_genreid = query.lastInsertId().toInt();
00337 }
00338 }
00339
00340
00341 QString strQuery;
00342 if (m_id < 1)
00343 {
00344 strQuery = "INSERT INTO music_songs ( directory_id,"
00345 " artist_id, album_id, name, genre_id,"
00346 " year, track, length, filename,"
00347 " rating, format, date_entered, date_modified ) "
00348 "VALUES ( "
00349 " :DIRECTORY, "
00350 " :ARTIST, :ALBUM, :TITLE, :GENRE,"
00351 " :YEAR, :TRACKNUM, :LENGTH, :FILENAME,"
00352 " :RATING, :FORMAT, :DATE_ADD, :DATE_MOD );";
00353 }
00354 else
00355 {
00356 strQuery = "UPDATE music_songs SET"
00357 " directory_id = :DIRECTORY"
00358 ", artist_id = :ARTIST"
00359 ", album_id = :ALBUM"
00360 ", name = :TITLE"
00361 ", genre_id = :GENRE"
00362 ", year = :YEAR"
00363 ", track = :TRACKNUM"
00364 ", length = :LENGTH"
00365 ", filename = :FILENAME"
00366 ", rating = :RATING"
00367 ", format = :FORMAT"
00368 ", date_modified = :DATE_MOD "
00369 "WHERE song_id= :ID ;";
00370 }
00371
00372 query.prepare(strQuery);
00373
00374 query.bindValue(":DIRECTORY", m_directoryid);
00375 query.bindValue(":ARTIST", m_artistid);
00376 query.bindValue(":ALBUM", m_albumid);
00377 query.bindValue(":TITLE", m_title.utf8());
00378 query.bindValue(":GENRE", m_genreid);
00379 query.bindValue(":YEAR", m_year);
00380 query.bindValue(":TRACKNUM", m_tracknum);
00381 query.bindValue(":LENGTH", m_length);
00382 query.bindValue(":FILENAME", sqlfilename.utf8());
00383 query.bindValue(":RATING", m_rating);
00384 query.bindValue(":FORMAT", m_format);
00385 query.bindValue(":DATE_MOD", QDateTime::currentDateTime());
00386
00387 if (m_id < 1)
00388 query.bindValue(":DATE_ADD", QDateTime::currentDateTime());
00389 else
00390 query.bindValue(":ID", m_id);
00391
00392 query.exec();
00393
00394 if (m_id < 1 && query.isActive() && 1 == query.numRowsAffected())
00395 m_id = query.lastInsertId().toInt();
00396
00397 if (! m_albumart.empty())
00398 {
00399 QValueList<struct AlbumArtImage>::iterator it;
00400 for ( it = m_albumart.begin(); it != m_albumart.end(); ++it )
00401 {
00402 query.prepare("SELECT albumart_id FROM music_albumart WHERE "
00403 "song_id=:SONGID AND imagetype=:TYPE;");
00404 query.bindValue(":TYPE", (*it).imageType);
00405 query.bindValue(":SONGID", m_id);
00406 query.exec();
00407
00408 if (query.next())
00409 {
00410 int artid = query.value(0).toInt();
00411
00412 query.prepare("UPDATE music_albumart SET "
00413 "filename=:FILENAME, imagetype=:TYPE, "
00414 "song_id=:SONGID, embedded=:EMBED "
00415 "WHERE albumart_id=:ARTID");
00416
00417 query.bindValue(":ARTID", artid);
00418 }
00419 else
00420 {
00421 query.prepare("INSERT INTO music_albumart ( filename, "
00422 "imagetype, song_id, embedded ) VALUES ( "
00423 ":FILENAME, :TYPE, :SONGID, :EMBED );");
00424 }
00425
00426 query.bindValue(":FILENAME", (*it).description);
00427 query.bindValue(":TYPE", (*it).imageType);
00428 query.bindValue(":SONGID", m_id);
00429 query.bindValue(":EMBED", 1);
00430
00431 query.exec();
00432 }
00433 }
00434
00435
00436 query.prepare("UPDATE music_albums SET compilation = :COMPILATION, year = :YEAR "
00437 "WHERE music_albums.album_id = :ALBUMID");
00438 query.bindValue(":ALBUMID", m_albumid);
00439 query.bindValue(":COMPILATION", m_compilation);
00440 query.bindValue(":YEAR", m_year);
00441
00442 if (!query.exec() || !query.isActive())
00443 {
00444 MythContext::DBError("music compilation update", query);
00445 return;
00446 }
00447 }
00448
00449
00450
00451 QString Metadata::m_formatnormalfileartist = "ARTIST";
00452 QString Metadata::m_formatnormalfiletrack = "TITLE";
00453 QString Metadata::m_formatnormalcdartist = "ARTIST";
00454 QString Metadata::m_formatnormalcdtrack = "TITLE";
00455 QString Metadata::m_formatcompilationfileartist = "COMPARTIST";
00456 QString Metadata::m_formatcompilationfiletrack = "TITLE (ARTIST)";
00457 QString Metadata::m_formatcompilationcdartist = "COMPARTIST";
00458 QString Metadata::m_formatcompilationcdtrack = "TITLE (ARTIST)";
00459
00460 void Metadata::setArtistAndTrackFormats()
00461 {
00462 QString tmp;
00463
00464 tmp = gContext->GetSetting("MusicFormatNormalFileArtist");
00465 if (!tmp.isEmpty())
00466 m_formatnormalfileartist = tmp;
00467
00468 tmp = gContext->GetSetting("MusicFormatNormalFileTrack");
00469 if (!tmp.isEmpty())
00470 m_formatnormalfiletrack = tmp;
00471
00472 tmp = gContext->GetSetting("MusicFormatNormalCDArtist");
00473 if (!tmp.isEmpty())
00474 m_formatnormalcdartist = tmp;
00475
00476 tmp = gContext->GetSetting("MusicFormatNormalCDTrack");
00477 if (!tmp.isEmpty())
00478 m_formatnormalcdtrack = tmp;
00479
00480 tmp = gContext->GetSetting("MusicFormatCompilationFileArtist");
00481 if (!tmp.isEmpty())
00482 m_formatcompilationfileartist = tmp;
00483
00484 tmp = gContext->GetSetting("MusicFormatCompilationFileTrack");
00485 if (!tmp.isEmpty())
00486 m_formatcompilationfiletrack = tmp;
00487
00488 tmp = gContext->GetSetting("MusicFormatCompilationCDArtist");
00489 if (!tmp.isEmpty())
00490 m_formatcompilationcdartist = tmp;
00491
00492 tmp = gContext->GetSetting("MusicFormatCompilationCDTrack");
00493 if (!tmp.isEmpty())
00494 m_formatcompilationcdtrack = tmp;
00495 }
00496
00497
00498 bool Metadata::determineIfCompilation(bool cd)
00499 {
00500 m_compilation = (!m_compilation_artist.isEmpty()
00501 && m_artist != m_compilation_artist);
00502 setCompilationFormatting(cd);
00503 return m_compilation;
00504 }
00505
00506
00507 inline QString Metadata::formatReplaceSymbols(const QString &format)
00508 {
00509 QString rv = format;
00510 rv.replace("COMPARTIST", m_compilation_artist);
00511 rv.replace("ARTIST", m_artist);
00512 rv.replace("TITLE", m_title);
00513 rv.replace("TRACK", QString("%1").arg(m_tracknum, 2));
00514 return rv;
00515 }
00516
00517 void Metadata::checkEmptyFields()
00518 {
00519 if (m_artist == "")
00520 m_artist = QObject::tr("Unknown Artist");
00521 if (m_compilation_artist == "")
00522 m_compilation_artist = m_artist;
00523 if (m_album == "")
00524 m_album = QObject::tr("Unknown Album");
00525 if (m_title == "")
00526 m_title = m_filename;
00527 if (m_genre == "")
00528 m_genre = QObject::tr("Unknown Genre");
00529
00530 }
00531
00532 inline void Metadata::setCompilationFormatting(bool cd)
00533 {
00534 QString format_artist, format_title;
00535
00536 if (!m_compilation
00537 || "" == m_compilation_artist
00538 || m_artist == m_compilation_artist)
00539 {
00540 if (!cd)
00541 {
00542 format_artist = m_formatnormalfileartist;
00543 format_title = m_formatnormalfiletrack;
00544 }
00545 else
00546 {
00547 format_artist = m_formatnormalcdartist;
00548 format_title = m_formatnormalcdtrack;
00549 }
00550 }
00551 else
00552 {
00553 if (!cd)
00554 {
00555 format_artist = m_formatcompilationfileartist;
00556 format_title = m_formatcompilationfiletrack;
00557 }
00558 else
00559 {
00560 format_artist = m_formatcompilationcdartist;
00561 format_title = m_formatcompilationcdtrack;
00562 }
00563 }
00564
00565
00566 m_formattedartist = formatReplaceSymbols(format_artist);
00567 m_formattedtitle = formatReplaceSymbols(format_title);
00568 }
00569
00570
00571 QString Metadata::FormatArtist()
00572 {
00573 if (m_formattedartist.isEmpty())
00574 setCompilationFormatting();
00575
00576 return m_formattedartist;
00577 }
00578
00579
00580 QString Metadata::FormatTitle()
00581 {
00582 if (m_formattedtitle.isEmpty())
00583 setCompilationFormatting();
00584
00585 return m_formattedtitle;
00586 }
00587
00588
00589 void Metadata::setField(const QString &field, const QString &data)
00590 {
00591 if (field == "artist")
00592 m_artist = data;
00593
00594
00595
00596
00597 else if (field == "compilation_artist")
00598 m_compilation_artist = data;
00599 else if (field == "album")
00600 m_album = data;
00601 else if (field == "title")
00602 m_title = data;
00603 else if (field == "genre")
00604 m_genre = data;
00605 else if (field == "filename")
00606 m_filename = data;
00607 else if (field == "year")
00608 m_year = data.toInt();
00609 else if (field == "tracknum")
00610 m_tracknum = data.toInt();
00611 else if (field == "length")
00612 m_length = data.toInt();
00613 else if (field == "compilation")
00614 m_compilation = (data.toInt() > 0);
00615
00616 else
00617 {
00618 VERBOSE(VB_IMPORTANT, QString("Something asked me to return data "
00619 "about a field called %1").arg(field));
00620 }
00621 }
00622
00623 void Metadata::getField(const QString &field, QString *data)
00624 {
00625 if (field == "artist")
00626 *data = FormatArtist();
00627 else if (field == "album")
00628 *data = m_album;
00629 else if (field == "title")
00630 *data = FormatTitle();
00631 else if (field == "genre")
00632 *data = m_genre;
00633 else
00634 {
00635 VERBOSE(VB_IMPORTANT, QString("Something asked me to return data "
00636 "about a field called %1").arg(field));
00637 *data = "I Dunno";
00638 }
00639 }
00640
00641 void Metadata::decRating()
00642 {
00643 if (m_rating > 0)
00644 {
00645 m_rating--;
00646 }
00647 m_changed = true;
00648 }
00649
00650 void Metadata::incRating()
00651 {
00652 if (m_rating < 10)
00653 {
00654 m_rating++;
00655 }
00656 m_changed = true;
00657 }
00658
00659 double Metadata::LastPlay()
00660 {
00661 QString timestamp = m_lastplay;
00662 timestamp = timestamp.replace(':', "");
00663 timestamp = timestamp.replace('T', "");
00664 timestamp = timestamp.replace('-', "");
00665
00666 return timestamp.toDouble();
00667 }
00668
00669 void Metadata::setLastPlay()
00670 {
00671 QDateTime cTime = QDateTime::currentDateTime();
00672 m_lastplay = cTime.toString("yyyyMMddhhmmss");
00673 m_changed = true;
00674 }
00675
00676 void Metadata::incPlayCount()
00677 {
00678 m_playcount++;
00679 m_changed = true;
00680 }
00681
00682 void Metadata::setEmbeddedAlbumArt(QValueList<struct AlbumArtImage> albumart)
00683 {
00684 m_albumart = albumart;
00685 }
00686
00687 QStringList Metadata::fillFieldList(QString field)
00688 {
00689 QStringList searchList;
00690 searchList.clear();
00691
00692 MSqlQuery query(MSqlQuery::InitCon());
00693 if ("artist" == field)
00694 {
00695 query.prepare("SELECT artist_name FROM music_artists ORDER BY artist_name;");
00696 }
00697 else if ("compilation_artist" == field)
00698 {
00699 query.prepare("SELECT DISTINCT artist_name FROM music_artists, music_albums where "
00700 "music_albums.artist_id=music_artists.artist_id ORDER BY artist_name");
00701 }
00702 else if ("album" == field)
00703 {
00704 query.prepare("SELECT album_name FROM music_albums ORDER BY album_name;");
00705 }
00706 else if ("title" == field)
00707 {
00708 query.prepare("SELECT name FROM music_songs ORDER BY name;");
00709 }
00710 else if ("genre" == field)
00711 {
00712 query.prepare("SELECT genre FROM music_genres ORDER BY genre;");
00713 }
00714 else
00715 {
00716 return searchList;
00717 }
00718
00719 if (query.exec() && query.isActive())
00720 {
00721 while (query.next())
00722 {
00723 searchList << QString::fromUtf8(query.value(0).toString());
00724 }
00725 }
00726 return searchList;
00727 }
00728
00729 QImage Metadata::getAlbumArt(void)
00730 {
00731 AlbumArtImages albumArt(this);
00732
00733 QImage image;
00734 ImageType type;
00735
00736 if (albumArt.isImageAvailable(IT_FRONTCOVER))
00737 type = IT_FRONTCOVER;
00738 else if (albumArt.isImageAvailable(IT_UNKNOWN))
00739 type = IT_UNKNOWN;
00740 else if (albumArt.isImageAvailable(IT_BACKCOVER))
00741 type = IT_BACKCOVER;
00742 else if (albumArt.isImageAvailable(IT_INLAY))
00743 type = IT_INLAY;
00744 else if (albumArt.isImageAvailable(IT_CD))
00745 type = IT_CD;
00746 else
00747 return image;
00748
00749 AlbumArtImage albumart_image = albumArt.getImage(type);
00750
00751 if (albumart_image.embedded)
00752 image = QImage(MetaIOTagLib::getAlbumArt(m_filename, type));
00753 else
00754 image = QImage(albumart_image.filename);
00755
00756 return image;
00757 }
00758
00759 QImage Metadata::getAlbumArt(ImageType type)
00760 {
00761 AlbumArtImages albumArt(this);
00762
00763 QImage image;
00764
00765 if (albumArt.isImageAvailable(type))
00766 {
00767 AlbumArtImage albumart_image = albumArt.getImage(type);
00768
00769 if (albumart_image.embedded)
00770 image = QImage(MetaIOTagLib::getAlbumArt(m_filename, type));
00771 else
00772 image = QImage(albumart_image.filename);
00773 }
00774
00775 return image;
00776 }
00777
00778
00779
00780 Metadata *Metadata::getMetadataFromID(int id)
00781 {
00782 Metadata *meta = NULL;
00783
00784 QString aquery = "SELECT music_songs.song_id, music_artists.artist_name, music_comp_artists.artist_name AS compilation_artist, "
00785 "music_albums.album_name, music_songs.name, music_genres.genre, music_songs.year, "
00786 "music_songs.track, music_songs.length, CONCAT_WS('/', "
00787 "music_directories.path, music_songs.filename) AS filename, "
00788 "music_songs.rating, music_songs.numplays, music_songs.lastplay, music_albums.compilation, "
00789 "music_songs.format "
00790 "FROM music_songs "
00791 "LEFT JOIN music_directories ON music_songs.directory_id=music_directories.directory_id "
00792 "LEFT JOIN music_artists ON music_songs.artist_id=music_artists.artist_id "
00793 "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id "
00794 "LEFT JOIN music_artists AS music_comp_artists ON music_albums.artist_id=music_comp_artists.artist_id "
00795 "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id "
00796 "WHERE music_songs.song_id = :TRACKID;";
00797
00798 QString filename, artist, album, title;
00799
00800 MSqlQuery query(MSqlQuery::InitCon());
00801 query.prepare(aquery);
00802 query.bindValue(":TRACKID", id);
00803 query.exec();
00804
00805 if (query.isActive() && query.size() > 0)
00806 {
00807 query.next();
00808 filename = QString::fromUtf8(query.value(9).toString());
00809 if (!filename.contains("://"))
00810 filename = m_startdir + filename;
00811
00812 artist = QString::fromUtf8(query.value(1).toString());
00813 if (artist.isEmpty())
00814 artist = QObject::tr("Unknown Artist");
00815
00816 album = QString::fromUtf8(query.value(3).toString());
00817 if (album.isEmpty())
00818 album = QObject::tr("Unknown Album");
00819
00820 title = QString::fromUtf8(query.value(4).toString());
00821 if (title.isEmpty())
00822 title = QObject::tr("Unknown Title");
00823
00824 meta = new Metadata(
00825 filename,
00826 artist,
00827 QString::fromUtf8(query.value(2).toString()),
00828 album,
00829 title,
00830 QString::fromUtf8(query.value(5).toString()),
00831 query.value(6).toInt(),
00832 query.value(7).toInt(),
00833 query.value(8).toInt(),
00834 query.value(0).toInt(),
00835 query.value(10).toInt(),
00836 query.value(11).toInt(),
00837 query.value(12).toString(),
00838 (query.value(13).toInt() > 0),
00839 query.value(14).toString());
00840 }
00841 else
00842 {
00843 VERBOSE(VB_IMPORTANT, QString("Track %1 not found!!").arg(id));
00844 return NULL;
00845 }
00846
00847 return meta;
00848 }
00849
00850
00851
00852 MetadataLoadingThread::MetadataLoadingThread(AllMusic *parent_ptr)
00853 {
00854 parent = parent_ptr;
00855 }
00856
00857 void MetadataLoadingThread::run()
00858 {
00859
00860
00861 parent->resync();
00862 }
00863
00864 AllMusic::AllMusic(QString path_assignment, QString a_startdir)
00865 {
00866 m_startdir = a_startdir;
00867 m_done_loading = false;
00868 m_numPcs = m_numLoaded = 0;
00869
00870 m_cd_title = QObject::tr("CD -- none");
00871
00872
00873 setSorting(path_assignment);
00874
00875 m_root_node = new MusicNode(QObject::tr("All My Music"), m_paths);
00876
00877
00878
00879
00880
00881
00882 m_metadata_loader = NULL;
00883 startLoading();
00884
00885 m_all_music.setAutoDelete(true);
00886
00887 m_last_listed = -1;
00888 }
00889
00890 AllMusic::~AllMusic()
00891 {
00892 m_all_music.clear();
00893
00894 delete m_root_node;
00895
00896 m_metadata_loader->wait();
00897 delete m_metadata_loader;
00898 }
00899
00900 bool AllMusic::cleanOutThreads()
00901 {
00902
00903
00904
00905
00906 if(m_metadata_loader->finished())
00907 {
00908 return true;
00909 }
00910
00911 m_metadata_loader->wait();
00912 return false;
00913 }
00914
00926 bool AllMusic::startLoading(void)
00927 {
00928
00929
00930 m_done_loading = false;
00931
00932 if (m_metadata_loader)
00933 {
00934 cleanOutThreads();
00935 delete m_metadata_loader;
00936 }
00937
00938 m_metadata_loader = new MetadataLoadingThread(this);
00939 m_metadata_loader->start();
00940
00941 return true;
00942 }
00943
00944 void AllMusic::resync()
00945 {
00946 m_done_loading = false;
00947
00948 QString aquery = "SELECT music_songs.song_id, music_artists.artist_name, music_comp_artists.artist_name AS compilation_artist, "
00949 "music_albums.album_name, music_songs.name, music_genres.genre, music_songs.year, "
00950 "music_songs.track, music_songs.length, CONCAT_WS('/', "
00951 "music_directories.path, music_songs.filename) AS filename, "
00952 "music_songs.rating, music_songs.numplays, music_songs.lastplay, music_albums.compilation, "
00953 "music_songs.format "
00954 "FROM music_songs "
00955 "LEFT JOIN music_directories ON music_songs.directory_id=music_directories.directory_id "
00956 "LEFT JOIN music_artists ON music_songs.artist_id=music_artists.artist_id "
00957 "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id "
00958 "LEFT JOIN music_artists AS music_comp_artists ON music_albums.artist_id=music_comp_artists.artist_id "
00959 "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id "
00960 "ORDER BY music_songs.song_id;";
00961
00962 QString filename, artist, album, title;
00963
00964 MSqlQuery query(MSqlQuery::InitCon());
00965 query.exec(aquery);
00966
00967 m_root_node->clear();
00968 m_all_music.clear();
00969
00970 m_numPcs = query.size() * 2;
00971 m_numLoaded = 0;
00972
00973 if (query.isActive() && query.size() > 0)
00974 {
00975 while (query.next())
00976 {
00977 filename = QString::fromUtf8(query.value(9).toString());
00978 if (!filename.contains("://"))
00979 filename = m_startdir + filename;
00980
00981 artist = QString::fromUtf8(query.value(1).toString());
00982 if (artist.isEmpty())
00983 artist = QObject::tr("Unknown Artist");
00984
00985 album = QString::fromUtf8(query.value(3).toString());
00986 if (album.isEmpty())
00987 album = QObject::tr("Unknown Album");
00988
00989 title = QString::fromUtf8(query.value(4).toString());
00990 if (title.isEmpty())
00991 title = QObject::tr("Unknown Title");
00992
00993 Metadata *temp = new Metadata(
00994 filename,
00995 artist,
00996 QString::fromUtf8(query.value(2).toString()),
00997 album,
00998 title,
00999 QString::fromUtf8(query.value(5).toString()),
01000 query.value(6).toInt(),
01001 query.value(7).toInt(),
01002 query.value(8).toInt(),
01003 query.value(0).toInt(),
01004 query.value(10).toInt(),
01005 query.value(11).toInt(),
01006 query.value(12).toString(),
01007 (query.value(13).toInt() > 0),
01008 query.value(14).toString());
01009
01010
01011 m_all_music.append(temp);
01012
01013
01014 if (query.at() == 0)
01015 {
01016 m_playcountMin = m_playcountMax = temp->PlayCount();
01017 m_lastplayMin = m_lastplayMax = temp->LastPlay();
01018 }
01019 else
01020 {
01021 int playCount = temp->PlayCount();
01022 double lastPlay = temp->LastPlay();
01023
01024 m_playcountMin = min(playCount, m_playcountMin);
01025 m_playcountMax = max(playCount, m_playcountMax);
01026 m_lastplayMin = min(lastPlay, m_lastplayMin);
01027 m_lastplayMax = max(lastPlay, m_lastplayMax);
01028 }
01029 m_numLoaded++;
01030 }
01031 }
01032 else
01033 {
01034 VERBOSE(VB_IMPORTANT, "MythMusic hasn't found any tracks! "
01035 "That's ok with me if it's ok with you.");
01036 }
01037
01038
01039
01040
01041 QPtrListIterator<Metadata> an_iterator( m_all_music );
01042 Metadata *map_add;
01043
01044 music_map.clear();
01045 while ( (map_add = an_iterator.current()) != 0 )
01046 {
01047 music_map[map_add->ID()] = map_add;
01048 ++an_iterator;
01049 }
01050
01051
01052
01053
01054 buildTree();
01055
01056 sortTree();
01057
01058 m_done_loading = true;
01059 }
01060
01061 void AllMusic::sortTree()
01062 {
01063 m_root_node->sort();
01064 }
01065
01066 void AllMusic::printTree()
01067 {
01068
01069
01070 cout << "Whole Music Tree" << endl;
01071 m_root_node->printYourself(0);
01072 }
01073
01074 void AllMusic::buildTree()
01075 {
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086 QPtrListIterator<Metadata> an_iterator( m_all_music );
01087 Metadata *inserter;
01088 MetadataPtrList list;
01089
01090 while ( (inserter = an_iterator.current()) != 0 )
01091 {
01092 if (inserter->isVisible())
01093 list.append(inserter);
01094 ++an_iterator;
01095
01096 m_numLoaded++;
01097 }
01098
01099 MusicTreeBuilder *builder = MusicTreeBuilder::createBuilder (m_paths);
01100 builder->makeTree (m_root_node, list);
01101 delete builder;
01102 }
01103
01104 void AllMusic::writeTree(GenericTree *tree_to_write_to)
01105 {
01106 m_root_node->writeTree(tree_to_write_to, 0);
01107 }
01108
01109 bool AllMusic::putYourselfOnTheListView(TreeCheckItem *where)
01110 {
01111 m_root_node->putYourselfOnTheListView(where, false);
01112 return true;
01113 }
01114
01115 void AllMusic::putCDOnTheListView(CDCheckItem *where)
01116 {
01117 ValueMetadata::iterator anit;
01118 for(anit = m_cd_data.begin(); anit != m_cd_data.end(); ++anit)
01119 {
01120 QString title_string = "";
01121 if((*anit).Title().length() > 0)
01122 {
01123 title_string = (*anit).FormatTitle();
01124 }
01125 else
01126 {
01127 title_string = QObject::tr("Unknown");
01128 }
01129 QString title_temp = QString("%1 - %2").arg((*anit).Track()).arg(title_string);
01130 QString level_temp = QObject::tr("title");
01131 CDCheckItem *new_item = new CDCheckItem(where, title_temp, level_temp,
01132 -(*anit).Track());
01133 new_item->setCheck(false);
01134 }
01135 }
01136
01137 QString AllMusic::getLabel(int an_id, bool *error_flag)
01138 {
01139 QString a_label = "";
01140 if(an_id > 0)
01141 {
01142
01143 if (!music_map.contains(an_id))
01144 {
01145 a_label = QString(QObject::tr("Missing database entry: %1")).arg(an_id);
01146 *error_flag = true;
01147 return a_label;
01148 }
01149
01150 a_label += music_map[an_id]->FormatArtist();
01151 a_label += " ~ ";
01152 a_label += music_map[an_id]->FormatTitle();
01153
01154
01155 if(a_label.length() < 1)
01156 {
01157 a_label = QObject::tr("Ooops");
01158 *error_flag = true;
01159 }
01160 else
01161 {
01162 *error_flag = false;
01163 }
01164 return a_label;
01165 }
01166 else
01167 {
01168 ValueMetadata::iterator anit;
01169 for(anit = m_cd_data.begin(); anit != m_cd_data.end(); ++anit)
01170 {
01171 if( (*anit).Track() == an_id * -1)
01172 {
01173 a_label = QString("(CD) %1 ~ %2").arg((*anit).FormatArtist())
01174 .arg((*anit).FormatTitle());
01175 *error_flag = false;
01176 return a_label;
01177 }
01178 }
01179 }
01180
01181 a_label = "";
01182 *error_flag = true;
01183 return a_label;
01184 }
01185
01186 Metadata* AllMusic::getMetadata(int an_id)
01187 {
01188 if(an_id > 0)
01189 {
01190 if (music_map.contains(an_id))
01191 {
01192 return music_map[an_id];
01193 }
01194 }
01195 else if(an_id < 0)
01196 {
01197 ValueMetadata::iterator anit;
01198 for(anit = m_cd_data.begin(); anit != m_cd_data.end(); ++anit)
01199 {
01200 if( (*anit).Track() == an_id * -1)
01201 {
01202 return &(*anit);
01203 }
01204 }
01205 }
01206 return NULL;
01207 }
01208
01209 bool AllMusic::updateMetadata(int an_id, Metadata *the_track)
01210 {
01211 if(an_id > 0)
01212 {
01213 Metadata *mdata = getMetadata(an_id);
01214 if (mdata)
01215 {
01216 *mdata = the_track;
01217 return true;
01218 }
01219 }
01220 return false;
01221 }
01222
01223 void AllMusic::save()
01224 {
01225
01226
01227
01228
01229 QPtrListIterator<Metadata> an_iterator( m_all_music );
01230 Metadata *searcher;
01231 while ( (searcher = an_iterator.current()) != 0 )
01232 {
01233 if(searcher->hasChanged())
01234 {
01235 searcher->persist();
01236 }
01237 ++an_iterator;
01238 }
01239 }
01240
01241 void AllMusic::clearCDData()
01242 {
01243 m_cd_data.clear();
01244 m_cd_title = QObject::tr("CD -- none");
01245 }
01246
01247 void AllMusic::addCDTrack(Metadata *the_track)
01248 {
01249 m_cd_data.append(*the_track);
01250 }
01251
01252 bool AllMusic::checkCDTrack(Metadata *the_track)
01253 {
01254 if (m_cd_data.count() < 1)
01255 {
01256 return false;
01257 }
01258 if (m_cd_data.last().FormatTitle() == the_track->FormatTitle())
01259 {
01260 return true;
01261 }
01262 return false;
01263 }
01264
01265 bool AllMusic::getCDMetadata(int the_track, Metadata *some_metadata)
01266 {
01267 ValueMetadata::iterator anit;
01268 for (anit = m_cd_data.begin(); anit != m_cd_data.end(); ++anit)
01269 {
01270 if ((*anit).Track() == the_track)
01271 {
01272 *some_metadata = (*anit);
01273 return true;
01274 }
01275
01276 }
01277 return false;
01278 }
01279
01280 void AllMusic::setSorting(QString a_paths)
01281 {
01282 m_paths = a_paths;
01283 MusicNode::SetStaticData(m_startdir, m_paths);
01284
01285 if (m_paths == "directory")
01286 return;
01287
01288
01289 QStringList tree_levels = QStringList::split(" ", m_paths);
01290 QStringList::const_iterator it = tree_levels.begin();
01291 for (; it != tree_levels.end(); ++it)
01292 {
01293 if (*it != "genre" &&
01294 *it != "artist" &&
01295 *it != "splitartist" &&
01296 *it != "splitartist1" &&
01297 *it != "album" &&
01298 *it != "title")
01299 {
01300 VERBOSE(VB_IMPORTANT, QString("AllMusic::setSorting() "
01301 "Unknown tree level '%1'").arg(*it));
01302 }
01303 }
01304 }
01305
01306 void AllMusic::setAllVisible(bool visible)
01307 {
01308 QPtrListIterator<Metadata> an_iterator( m_all_music );
01309 Metadata *md;
01310 while ( (md = an_iterator.current()) != 0 )
01311 {
01312 md->setVisible(visible);
01313 ++an_iterator;
01314 }
01315 }
01316
01317 MusicNode::MusicNode(const QString &a_title, const QString &tree_level)
01318 {
01319 my_title = a_title;
01320 my_level = tree_level;
01321 my_subnodes.setAutoDelete(true);
01322 setPlayCountMin(0);
01323 setPlayCountMax(0);
01324 setLastPlayMin(0);
01325 setLastPlayMax(0);
01326 }
01327
01328 MusicNode::~MusicNode()
01329 {
01330 my_subnodes.clear();
01331 }
01332
01333
01334
01335 QString MusicNode::m_startdir = "";
01336 QString MusicNode::m_paths = "";
01337 int MusicNode::m_RatingWeight = 2;
01338 int MusicNode::m_PlayCountWeight = 2;
01339 int MusicNode::m_LastPlayWeight = 2;
01340 int MusicNode::m_RandomWeight = 2;
01341
01342 void MusicNode::SetStaticData(const QString &startdir, const QString &paths)
01343 {
01344 m_startdir = startdir;
01345 m_paths = paths;
01346 m_RatingWeight = gContext->GetNumSetting("IntelliRatingWeight", 2);
01347 m_PlayCountWeight = gContext->GetNumSetting("IntelliPlayCountWeight", 2);
01348 m_LastPlayWeight = gContext->GetNumSetting("IntelliLastPlayWeight", 2);
01349 m_RandomWeight = gContext->GetNumSetting("IntelliRandomWeight", 2);
01350 }
01351
01352 void MusicNode::putYourselfOnTheListView(TreeCheckItem *parent, bool show_node)
01353 {
01354 TreeCheckItem *current_parent;
01355
01356 if (show_node)
01357 {
01358 QString title_temp = my_title;
01359 QString level_temp = my_level;
01360 current_parent = new TreeCheckItem(parent, title_temp, level_temp, 0);
01361 }
01362 else
01363 {
01364 current_parent = parent;
01365 }
01366
01367
01368 QPtrListIterator<Metadata> anit(my_tracks);
01369 Metadata *a_track;
01370 while ((a_track = anit.current() ) != 0)
01371 {
01372 QString title_temp = QString(QObject::tr("%1 - %2"))
01373 .arg(a_track->Track()).arg(a_track->Title());
01374 QString level_temp = QObject::tr("title");
01375 TreeCheckItem *new_item = new TreeCheckItem(current_parent, title_temp,
01376 level_temp, a_track->ID());
01377 ++anit;
01378 new_item->setCheck(false);
01379 }
01380
01381
01382 QPtrListIterator<MusicNode> iter(my_subnodes);
01383 MusicNode *sub_traverse;
01384 while ((sub_traverse = iter.current() ) != 0)
01385 {
01386 sub_traverse->putYourselfOnTheListView(current_parent, true);
01387 ++iter;
01388 }
01389
01390 }
01391
01392 void MusicNode::writeTree(GenericTree *tree_to_write_to, int a_counter)
01393 {
01394
01395 GenericTree *sub_node = tree_to_write_to->addNode(my_title);
01396 sub_node->setAttribute(0, 0);
01397 sub_node->setAttribute(1, a_counter);
01398 sub_node->setAttribute(2, a_counter);
01399 sub_node->setAttribute(3, a_counter);
01400 sub_node->setAttribute(4, a_counter);
01401 sub_node->setAttribute(5, a_counter);
01402
01403 QPtrListIterator<Metadata> anit(my_tracks);
01404 Metadata *a_track;
01405 int track_counter = 0;
01406 anit.toFirst();
01407 while( (a_track = anit.current() ) != 0)
01408 {
01409 QString title_temp = QString(QObject::tr("%1 - %2")).arg(a_track->Track()).arg(a_track->Title());
01410 GenericTree *subsub_node = sub_node->addNode(title_temp, a_track->ID(), true);
01411 subsub_node->setAttribute(0, 1);
01412 subsub_node->setAttribute(1, track_counter);
01413 subsub_node->setAttribute(2, rand());
01414
01415
01416
01417
01418 int rating = a_track->Rating();
01419 int playcount = a_track->PlayCount();
01420 double lastplaydbl = a_track->LastPlay();
01421 double ratingValue = (double)(rating) / 10;
01422 double playcountValue, lastplayValue;
01423
01424 if (m_playcountMax == m_playcountMin)
01425 playcountValue = 0;
01426 else
01427 playcountValue = ((m_playcountMin - (double)playcount) / (m_playcountMax - m_playcountMin) + 1);
01428 if (m_lastplayMax == m_lastplayMin)
01429 lastplayValue = 0;
01430 else
01431 lastplayValue = ((m_lastplayMin - lastplaydbl) / (m_lastplayMax - m_lastplayMin) + 1);
01432
01433 double rating_value = (m_RatingWeight * ratingValue + m_PlayCountWeight * playcountValue +
01434 m_LastPlayWeight * lastplayValue + m_RandomWeight * (double)rand() /
01435 (RAND_MAX + 1.0));
01436 int integer_rating = (int) (4000001 - rating_value * 10000);
01437 subsub_node->setAttribute(3, integer_rating);
01438 ++track_counter;
01439 ++anit;
01440 }
01441
01442
01443 QPtrListIterator<MusicNode> iter(my_subnodes);
01444 MusicNode *sub_traverse;
01445 int another_counter = 0;
01446 iter.toFirst();
01447 while( (sub_traverse = iter.current() ) != 0)
01448 {
01449 sub_traverse->setPlayCountMin(m_playcountMin);
01450 sub_traverse->setPlayCountMax(m_playcountMax);
01451 sub_traverse->setLastPlayMin(m_lastplayMin);
01452 sub_traverse->setLastPlayMax(m_lastplayMax);
01453 sub_traverse->writeTree(sub_node, another_counter);
01454 ++another_counter;
01455 ++iter;
01456 }
01457 }
01458
01459
01460 void MusicNode::sort()
01461 {
01462
01463 my_tracks.sort();
01464
01465
01466 my_subnodes.sort();
01467
01468
01469 QPtrListIterator<MusicNode> iter(my_subnodes);
01470 MusicNode *crawler;
01471 while ( (crawler = iter.current()) != 0 )
01472 {
01473 crawler->sort();
01474 ++iter;
01475 }
01476 }
01477
01478
01479 void MusicNode::printYourself(int indent_level)
01480 {
01481
01482 for(int i = 0; i < (indent_level) * 4; ++i)
01483 {
01484 cout << " " ;
01485 }
01486 cout << my_title << endl;
01487
01488 QPtrListIterator<Metadata> anit(my_tracks);
01489 Metadata *a_track;
01490 while( (a_track = anit.current() ) != 0)
01491 {
01492 for(int j = 0; j < (indent_level + 1) * 4; j++)
01493 {
01494 cout << " " ;
01495 }
01496 cout << a_track->Title() << endl ;
01497 ++anit;
01498 }
01499
01500 QPtrListIterator<MusicNode> iter(my_subnodes);
01501 MusicNode *print;
01502 while( (print = iter.current() ) != 0)
01503 {
01504 print->printYourself(indent_level + 1);
01505 ++iter;
01506 }
01507 }
01508
01509
01510
01511 int MetadataPtrList::compareItems(QPtrCollection::Item item1,
01512 QPtrCollection::Item item2)
01513 {
01514 return ((Metadata*)item1)->compare((Metadata*)item2);
01515 }
01516
01517 int MusicNodePtrList::compareItems (QPtrCollection::Item item1,
01518 QPtrCollection::Item item2)
01519 {
01520 MusicNode *itemA = (MusicNode*)item1;
01521 MusicNode *itemB = (MusicNode*)item2;
01522
01523 QString title1 = itemA->getTitle().lower();
01524 QString title2 = itemB->getTitle().lower();
01525
01526
01527 if (title1.left(4) == thePrefix)
01528 title1 = title1.mid(4);
01529 if (title2.left(4) == thePrefix)
01530 title2 = title2.mid(4);
01531
01532 return title1.localeAwareCompare(title2);
01533 }
01534
01535
01536
01537 AlbumArtImages::AlbumArtImages(Metadata *metadata)
01538 : m_parent(metadata)
01539 {
01540 m_imageList.setAutoDelete(true);
01541
01542 findImages();
01543 }
01544
01545 void AlbumArtImages::findImages(void)
01546 {
01547 m_imageList.clear();
01548
01549 if (m_parent == NULL)
01550 return;
01551
01552 int trackid = m_parent->ID();
01553
01554 if (trackid == 0)
01555 return;
01556
01557 QFileInfo fi(m_parent->Filename());
01558 QString dir = fi.dirPath(true);
01559 dir.remove(0, Metadata::GetStartdir().length());
01560
01561 MSqlQuery query(MSqlQuery::InitCon());
01562 query.prepare("SELECT albumart_id, CONCAT_WS('/', music_directories.path, "
01563 "music_albumart.filename), music_albumart.imagetype, "
01564 "music_albumart.embedded "
01565 "FROM music_albumart "
01566 "LEFT JOIN music_directories ON "
01567 "music_directories.directory_id=music_albumart.directory_id "
01568 "WHERE music_directories.path = :DIR "
01569 "OR song_id = :SONGID "
01570 "ORDER BY music_albumart.imagetype;");
01571 query.bindValue(":DIR", dir.utf8());
01572 query.bindValue(":SONGID", trackid);
01573 if (query.exec())
01574 {
01575 while (query.next())
01576 {
01577 AlbumArtImage *image = new AlbumArtImage;
01578 image->id = query.value(0).toInt();
01579 image->filename = Metadata::GetStartdir() + "/" +
01580 QString::fromUtf8(query.value(1).toString());
01581 image->imageType = (ImageType) query.value(2).toInt();
01582 image->typeName = getTypeName(image->imageType);
01583 if (query.value(3).toInt() == 1)
01584 {
01585 image->description = query.value(1).toString();
01586 image->embedded = true;
01587 }
01588 else {
01589 image->embedded = false;
01590 }
01591 m_imageList.append(image);
01592 }
01593 }
01594 }
01595
01596 AlbumArtImage AlbumArtImages::getImage(ImageType type)
01597 {
01598
01599 AlbumArtImage *image;
01600
01601 for (image = m_imageList.first(); image; image = m_imageList.next())
01602 {
01603 if (image->imageType == type)
01604 return *image;
01605 }
01606
01607 return *image;
01608 }
01609
01610 QStringList AlbumArtImages::getImageFilenames()
01611 {
01612 QStringList paths;
01613
01614 AlbumArtImage *image;
01615
01616 for (image = m_imageList.first(); image; image = m_imageList.next())
01617 {
01618 paths += image->filename;
01619 }
01620
01621 return paths;
01622 }
01623
01624 AlbumArtImage AlbumArtImages::getImageAt(uint index)
01625 {
01626 return *(m_imageList.at(index));
01627 }
01628
01629 bool AlbumArtImages::isImageAvailable(ImageType type)
01630 {
01631
01632 AlbumArtImage *image;
01633
01634 for (image = m_imageList.first(); image; image = m_imageList.next())
01635 {
01636 if (image->imageType == type)
01637 return true;
01638 }
01639
01640 return false;
01641 }
01642
01643 bool AlbumArtImages::saveImageType(const int id, ImageType type)
01644 {
01645 MSqlQuery query(MSqlQuery::InitCon());
01646 query.prepare("UPDATE music_albumart SET imagetype = :TYPE "
01647 "WHERE albumart_id = :ID");
01648 query.bindValue(":TYPE", type);
01649 query.bindValue(":ID", id);
01650 return (query.exec());
01651 }
01652
01653 QString AlbumArtImages::getTypeName(ImageType type)
01654 {
01655
01656 static const char* type_strings[] = {
01657 QT_TR_NOOP("Unknown"),
01658 QT_TR_NOOP("Front Cover"),
01659 QT_TR_NOOP("Back Cover"),
01660 QT_TR_NOOP("CD"),
01661 QT_TR_NOOP("Inlay")
01662 };
01663
01664 return tr(type_strings[type]);
01665 }
01666
01667
01668 ImageType AlbumArtImages::guessImageType(const QString &filename)
01669 {
01670 ImageType type = IT_FRONTCOVER;
01671
01672 if (filename.contains(tr("front"), false))
01673 type = IT_FRONTCOVER;
01674 else if (filename.contains(tr("back"), false))
01675 type = IT_BACKCOVER;
01676 else if (filename.contains(tr("inlay"), false))
01677 type = IT_INLAY;
01678 else if (filename.contains(tr("cd"), false))
01679 type = IT_CD;
01680 else if (filename.contains(tr("cover"), false))
01681 type = IT_FRONTCOVER;
01682
01683 return type;
01684 }
01685
01686 MusicData::MusicData(void)
01687 {
01688 paths = "";
01689 startdir = "";
01690 all_playlists = NULL;
01691 all_music = NULL;
01692 runPost = false;
01693 }
01694
01695 MusicData::~MusicData(void)
01696 {
01697 if (all_playlists)
01698 {
01699 delete all_playlists;
01700 all_playlists = NULL;
01701 }
01702
01703 if (all_music)
01704 {
01705 delete all_music;
01706 all_music = NULL;
01707 }
01708 }
01709
01710