Changeset View
Changeset View
Standalone View
Standalone View
src/core-impl/collections/db/sql/SqlMeta.cpp
Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Line(s) | |||||
54 | #include <QWriteLocker> | 54 | #include <QWriteLocker> | ||
55 | #include <QMutexLocker> | 55 | #include <QMutexLocker> | ||
56 | #include <QCryptographicHash> | 56 | #include <QCryptographicHash> | ||
57 | 57 | | |||
58 | #include <KCodecs> | 58 | #include <KCodecs> | ||
59 | #include <KLocalizedString> | 59 | #include <KLocalizedString> | ||
60 | #include <ThreadWeaver/Queue> | 60 | #include <ThreadWeaver/Queue> | ||
61 | 61 | | |||
62 | #include <thread> | | |||
63 | | ||||
64 | 62 | | |||
65 | // additional constants | 63 | // additional constants | ||
66 | namespace Meta | 64 | namespace Meta | ||
67 | { | 65 | { | ||
68 | static const qint64 valAlbumId = valCustom + 1; | 66 | static const qint64 valAlbumId = valCustom + 1; | ||
69 | } | 67 | } | ||
70 | 68 | | |||
71 | using namespace Meta; | 69 | using namespace Meta; | ||
▲ Show 20 Lines • Show All 1394 Lines • ▼ Show 20 Line(s) | 1462 | SqlAlbum::SqlAlbum( Collections::SqlCollection *collection, int id, const QString &name, int artist ) | |||
1466 | , m_collection( collection ) | 1464 | , m_collection( collection ) | ||
1467 | , m_name( name ) | 1465 | , m_name( name ) | ||
1468 | , m_id( id ) | 1466 | , m_id( id ) | ||
1469 | , m_artistId( artist ) | 1467 | , m_artistId( artist ) | ||
1470 | , m_imageId( -1 ) | 1468 | , m_imageId( -1 ) | ||
1471 | , m_hasImage( false ) | 1469 | , m_hasImage( false ) | ||
1472 | , m_hasImageChecked( false ) | 1470 | , m_hasImageChecked( false ) | ||
1473 | , m_unsetImageId( -1 ) | 1471 | , m_unsetImageId( -1 ) | ||
1474 | , m_tracksLoaded( false ) | 1472 | , m_tracksLoaded( NotLoaded ) | ||
1475 | , m_suppressAutoFetch( false ) | 1473 | , m_suppressAutoFetch( false ) | ||
1476 | , m_mutex( QMutex::Recursive ) | 1474 | , m_mutex( QMutex::Recursive ) | ||
1477 | { | 1475 | { | ||
1478 | Q_ASSERT( m_collection ); | 1476 | Q_ASSERT( m_collection ); | ||
1479 | Q_ASSERT( m_id > 0 ); | 1477 | Q_ASSERT( m_id > 0 ); | ||
1480 | } | 1478 | } | ||
1481 | 1479 | | |||
1482 | Meta::SqlAlbum::~SqlAlbum() | 1480 | Meta::SqlAlbum::~SqlAlbum() | ||
1483 | { | 1481 | { | ||
1484 | CoverCache::invalidateAlbum( this ); | 1482 | CoverCache::invalidateAlbum( this ); | ||
1485 | } | 1483 | } | ||
1486 | 1484 | | |||
1487 | void | 1485 | void | ||
1488 | SqlAlbum::invalidateCache() | 1486 | SqlAlbum::invalidateCache() | ||
1489 | { | 1487 | { | ||
1490 | QMutexLocker locker( &m_mutex ); | 1488 | QMutexLocker locker( &m_mutex ); | ||
1491 | m_tracksLoaded = false; | 1489 | m_tracksLoaded = NotLoaded; | ||
1492 | m_hasImage = false; | 1490 | m_hasImage = false; | ||
1493 | m_hasImageChecked = false; | 1491 | m_hasImageChecked = false; | ||
1494 | m_tracks.clear(); | 1492 | m_tracks.clear(); | ||
1495 | } | 1493 | } | ||
1496 | 1494 | | |||
1497 | TrackList | 1495 | TrackList | ||
1498 | SqlAlbum::tracks() | 1496 | SqlAlbum::tracks() | ||
1499 | { | 1497 | { | ||
1498 | bool startQuery = false; | ||||
1499 | | ||||
1500 | { | 1500 | { | ||
1501 | QMutexLocker locker( &m_mutex ); | 1501 | QMutexLocker locker( &m_mutex ); | ||
1502 | if( m_tracksLoaded ) | 1502 | if( m_tracksLoaded == Loaded ) | ||
1503 | return m_tracks; | 1503 | return m_tracks; | ||
1504 | else if( m_tracksLoaded == NotLoaded ) | ||||
1505 | { | ||||
1506 | startQuery = true; | ||||
1507 | m_tracksLoaded = Loading; | ||||
1508 | } | ||||
1504 | } | 1509 | } | ||
1505 | 1510 | | |||
1511 | if( startQuery ) | ||||
1512 | { | ||||
1506 | // when running the query maker don't lock. might lead to deadlock via registry | 1513 | // when running the query maker don't lock. might lead to deadlock via registry | ||
1507 | Collections::SqlQueryMaker *qm = static_cast< Collections::SqlQueryMaker* >( m_collection->queryMaker() ); | 1514 | Collections::SqlQueryMaker *qm = static_cast< Collections::SqlQueryMaker* >( m_collection->queryMaker() ); | ||
1508 | qm->setQueryType( Collections::QueryMaker::Track ); | 1515 | qm->setQueryType( Collections::QueryMaker::Track ); | ||
1509 | qm->addMatch( Meta::AlbumPtr( this ) ); | 1516 | qm->addMatch( Meta::AlbumPtr( this ) ); | ||
1510 | qm->orderBy( Meta::valDiscNr ); | 1517 | qm->orderBy( Meta::valDiscNr ); | ||
1511 | qm->orderBy( Meta::valTrackNr ); | 1518 | qm->orderBy( Meta::valTrackNr ); | ||
1512 | qm->orderBy( Meta::valTitle ); | 1519 | qm->orderBy( Meta::valTitle ); | ||
1513 | qm->setBlocking( true ); | 1520 | qm->setBlocking( true ); | ||
1514 | qm->run(); | 1521 | qm->run(); | ||
1515 | 1522 | | |||
1516 | { | 1523 | { | ||
1517 | QMutexLocker locker( &m_mutex ); | 1524 | QMutexLocker locker( &m_mutex ); | ||
1518 | m_tracks = qm->tracks(); | 1525 | m_tracks = qm->tracks(); | ||
1519 | m_tracksLoaded = true; | 1526 | m_tracksLoaded = Loaded; | ||
1520 | delete qm; | 1527 | delete qm; | ||
1521 | return m_tracks; | 1528 | return m_tracks; | ||
1522 | } | 1529 | } | ||
1523 | } | 1530 | } | ||
1531 | else | ||||
1532 | { | ||||
1533 | // Wait for tracks to be loaded | ||||
1534 | forever | ||||
1535 | { | ||||
1536 | QMutexLocker locker( &m_mutex ); | ||||
1537 | if( m_tracksLoaded == Loaded ) | ||||
1538 | return m_tracks; | ||||
1539 | else | ||||
1540 | QThread::yieldCurrentThread(); | ||||
1541 | } | ||||
1542 | } | ||||
1543 | } | ||||
1524 | 1544 | | |||
1525 | // note for internal implementation: | 1545 | // note for internal implementation: | ||
1526 | // if hasImage returns true then m_imagePath is set | 1546 | // if hasImage returns true then m_imagePath is set | ||
1527 | bool | 1547 | bool | ||
1528 | SqlAlbum::hasImage( int size ) const | 1548 | SqlAlbum::hasImage( int size ) const | ||
1529 | { | 1549 | { | ||
1530 | Q_UNUSED(size); // we have every size if we have an image at all | 1550 | Q_UNUSED(size); // we have every size if we have an image at all | ||
1531 | QMutexLocker locker( &m_mutex ); | 1551 | QMutexLocker locker( &m_mutex ); | ||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Line(s) | 1624 | if( image.isNull() ) | |||
1605 | image = QImage( m_imagePath ); | 1625 | image = QImage( m_imagePath ); | ||
1606 | 1626 | | |||
1607 | if( image.isNull() ) | 1627 | if( image.isNull() ) | ||
1608 | return Meta::Album::image( size ); | 1628 | return Meta::Album::image( size ); | ||
1609 | 1629 | | |||
1610 | if( size > 1 && size < 1000 ) | 1630 | if( size > 1 && size < 1000 ) | ||
1611 | { | 1631 | { | ||
1612 | image = image.scaled( size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation ); | 1632 | image = image.scaled( size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation ); | ||
1613 | std::thread thread( QOverload<const QString&, const char*, int>::of( &QImage::save ), image, cachedImagePath, "PNG", -1 ); | 1633 | image.save( cachedImagePath, "PNG", -1 ); | ||
1614 | thread.detach(); | | |||
1615 | } | 1634 | } | ||
1616 | 1635 | | |||
1617 | return image; | 1636 | return image; | ||
1618 | } | 1637 | } | ||
1619 | 1638 | | |||
1620 | QUrl | 1639 | QUrl | ||
1621 | SqlAlbum::imageLocation( int size ) | 1640 | SqlAlbum::imageLocation( int size ) | ||
1622 | { | 1641 | { | ||
Show All 26 Lines | |||||
1649 | 1668 | | |||
1650 | void | 1669 | void | ||
1651 | SqlAlbum::setImage( const QImage &image ) | 1670 | SqlAlbum::setImage( const QImage &image ) | ||
1652 | { | 1671 | { | ||
1653 | // the unnamed album is special. it will never have an image | 1672 | // the unnamed album is special. it will never have an image | ||
1654 | if( m_name.isEmpty() ) | 1673 | if( m_name.isEmpty() ) | ||
1655 | return; | 1674 | return; | ||
1656 | 1675 | | |||
1657 | QMutexLocker locker( &m_mutex ); | | |||
1658 | if( image.isNull() ) | 1676 | if( image.isNull() ) | ||
1659 | return; | 1677 | return; | ||
1660 | 1678 | | |||
1679 | QMutexLocker locker( &m_mutex ); | ||||
1680 | | ||||
1661 | // removeImage() will destroy all scaled cached versions of the artwork | 1681 | // removeImage() will destroy all scaled cached versions of the artwork | ||
1662 | // and remove references from the database if required. | 1682 | // and remove references from the database if required. | ||
1663 | removeImage(); | 1683 | removeImage(); | ||
1664 | 1684 | | |||
1665 | QString path = largeDiskCachePath(); | 1685 | QString path = largeDiskCachePath(); | ||
1666 | // make sure not to overwrite existing images | 1686 | // make sure not to overwrite existing images | ||
1667 | while( QFile(path).exists() ) | 1687 | while( QFile(path).exists() ) | ||
1668 | path += '_'; // not that nice but it shouldn't happen that often. | 1688 | path += '_'; // not that nice but it shouldn't happen that often. | ||
1669 | 1689 | | |||
1670 | std::thread thread( QOverload<const QString&, const char*, int>::of( &QImage::save ), image, path, "JPG", -1 ); | 1690 | image.save( path, "JPG", -1 ); | ||
1671 | thread.detach(); | | |||
1672 | setImage( path ); | 1691 | setImage( path ); | ||
1673 | 1692 | | |||
1674 | locker.unlock(); | 1693 | locker.unlock(); | ||
1675 | notifyObservers(); | 1694 | notifyObservers(); | ||
1676 | 1695 | | |||
1677 | // -- write back the album cover if allowed | 1696 | // -- write back the album cover if allowed | ||
1678 | if( AmarokConfig::writeBackCover() ) | 1697 | if( AmarokConfig::writeBackCover() ) | ||
1679 | { | 1698 | { | ||
▲ Show 20 Lines • Show All 232 Lines • ▼ Show 20 Line(s) | 1895 | { | |||
1912 | m_imagePath.clear(); | 1931 | m_imagePath.clear(); | ||
1913 | return m_imagePath; | 1932 | return m_imagePath; | ||
1914 | } | 1933 | } | ||
1915 | 1934 | | |||
1916 | // note: we won't notify the observers. we are a private function. the caller must do that. | 1935 | // note: we won't notify the observers. we are a private function. the caller must do that. | ||
1917 | void | 1936 | void | ||
1918 | SqlAlbum::setImage( const QString &path ) | 1937 | SqlAlbum::setImage( const QString &path ) | ||
1919 | { | 1938 | { | ||
1920 | if( m_imagePath == path ) | | |||
1921 | return; | | |||
1922 | if( m_name.isEmpty() ) // the empty album never has an image | 1939 | if( m_name.isEmpty() ) // the empty album never has an image | ||
1923 | return; | 1940 | return; | ||
1924 | 1941 | | |||
1925 | QMutexLocker locker( &m_mutex ); | 1942 | QMutexLocker locker( &m_mutex ); | ||
1926 | 1943 | | |||
1927 | QString imagePath = path; | 1944 | if( m_imagePath == path ) | ||
1945 | return; | ||||
1928 | 1946 | | |||
1929 | QString query = "SELECT id FROM images WHERE path = '%1'"; | 1947 | QString query = "SELECT id FROM images WHERE path = '%1'"; | ||
1930 | query = query.arg( m_collection->sqlStorage()->escape( imagePath ) ); | 1948 | query = query.arg( m_collection->sqlStorage()->escape( path ) ); | ||
1931 | QStringList res = m_collection->sqlStorage()->query( query ); | 1949 | QStringList res = m_collection->sqlStorage()->query( query ); | ||
1932 | 1950 | | |||
1933 | if( res.isEmpty() ) | 1951 | if( res.isEmpty() ) | ||
1934 | { | 1952 | { | ||
1935 | QString insert = QString( "INSERT INTO images( path ) VALUES ( '%1' )" ) | 1953 | QString insert = QString( "INSERT INTO images( path ) VALUES ( '%1' )" ) | ||
1936 | .arg( m_collection->sqlStorage()->escape( imagePath ) ); | 1954 | .arg( m_collection->sqlStorage()->escape( path ) ); | ||
1937 | m_imageId = m_collection->sqlStorage()->insert( insert, "images" ); | 1955 | m_imageId = m_collection->sqlStorage()->insert( insert, "images" ); | ||
1938 | } | 1956 | } | ||
1939 | else | 1957 | else | ||
1940 | m_imageId = res.first().toInt(); | 1958 | m_imageId = res.first().toInt(); | ||
1941 | 1959 | | |||
1942 | if( m_imageId >= 0 ) | 1960 | if( m_imageId >= 0 ) | ||
1943 | { | 1961 | { | ||
1944 | query = QString("UPDATE albums SET image = %1 WHERE albums.id = %2" ) | 1962 | query = QString("UPDATE albums SET image = %1 WHERE albums.id = %2" ) | ||
1945 | .arg( QString::number( m_imageId ), QString::number( m_id ) ); | 1963 | .arg( QString::number( m_imageId ), QString::number( m_id ) ); | ||
1946 | m_collection->sqlStorage()->query( query ); | 1964 | m_collection->sqlStorage()->query( query ); | ||
1947 | 1965 | | |||
1948 | m_imagePath = imagePath; | 1966 | m_imagePath = path; | ||
1949 | m_hasImage = true; | 1967 | m_hasImage = true; | ||
1950 | m_hasImageChecked = true; | 1968 | m_hasImageChecked = true; | ||
1951 | CoverCache::invalidateAlbum( this ); | 1969 | CoverCache::invalidateAlbum( this ); | ||
1952 | } | 1970 | } | ||
1953 | } | 1971 | } | ||
1954 | 1972 | | |||
1955 | /** Set the compilation flag. | 1973 | /** Set the compilation flag. | ||
1956 | * Actually it does not cange this album but instead moves | 1974 | * Actually it does not cange this album but instead moves | ||
▲ Show 20 Lines • Show All 296 Lines • Show Last 20 Lines |