extragear/multimedia/amarok/src/collection/sqlcollection
Seb Ruiz
ruiz at kde.org
Sun Jun 8 14:46:23 CEST 2008
SVN commit 818371 by seb:
Implements cover art retrieval from the file system during a media scan. This creates a new database table `images` and augments the `albums` table to add a new column `image`.
Images are stored in the database but not yet retrieved by the Meta internals.
Max: is my implementation in line with how you imagined it would be done?
CCMAIL: amarok-devel at kde.org
M +27 -3 DatabaseUpdater.cpp
M +16 -1 ScanManager.cpp
M +55 -1 ScanResultProcessor.cpp
M +4 -2 ScanResultProcessor.h
--- trunk/extragear/multimedia/amarok/src/collection/sqlcollection/DatabaseUpdater.cpp #818370:818371
@@ -90,10 +90,12 @@
QString c = "CREATE TEMPORARY TABLE albums_temp "
"(id " + m_collection->idType() +
",name " + m_collection->textColumnType() + " NOT NULL"
- ",artist INTEGER);";
+ ",artist INTEGER" +
+ ",image INTEGER);";
m_collection->query( c );
m_collection->query( "CREATE INDEX albums_temp_name ON albums_temp(name);" );
m_collection->query( "CREATE INDEX albums_temp_artist ON albums_temp(artist);" );
+ m_collection->query( "CREATE INDEX albums_temp_image ON albums_temp(image);" );
m_collection->query( "CREATE UNIQUE INDEX albums_temp_name_artist ON albums_temp(name,artist);" );
//the index below should not be necessary. uncomment if a query plan shows it is
//m_collection->query( "CREATE UNIQUE INDEX albums_artist_name ON albums(artist,name);" );
@@ -120,6 +122,13 @@
m_collection->query( "CREATE UNIQUE INDEX years_temp_name ON years_temp(name);" );
}
{
+ QString create = "CREATE TEMPORARY TABLE images_temp "
+ "(id " + m_collection->idType() +
+ ",path " + m_collection->textColumnType() + " NOT NULL);";
+ m_collection->query( create );
+ m_collection->query( "CREATE UNIQUE INDEX images_temp_name ON images_temp(path);" );
+ }
+ {
QString c = "CREATE TEMPORARY TABLE tracks_temp "
"(id " + m_collection->idType() +
",url INTEGER"
@@ -156,6 +165,7 @@
m_collection->query( "INSERT INTO artists_temp SELECT * FROM artists;" );
m_collection->query( "INSERT INTO years_temp SELECT * FROM years;" );
m_collection->query( "INSERT INTO albums_temp SELECT * FROM albums;" );
+ m_collection->query( "INSERT INTO images_temp SELECT * FROM images;" );
m_collection->query( "INSERT INTO genres_temp SELECT * FROM genres;" );
m_collection->query( "INSERT INTO composers_temp SELECT * FROM composers;" );
m_collection->query( "INSERT INTO tracks_temp SELECT * FROM tracks;" );
@@ -173,6 +183,7 @@
{
m_collection->query( "DELETE FROM composers;" );
m_collection->query( "DELETE FROM genres;" );
+ m_collection->query( "DELETE FROM images;" );
m_collection->query( "DELETE FROM albums;" );
m_collection->query( "DELETE FROM years;" );
m_collection->query( "DELETE FROM artists;" );
@@ -186,6 +197,7 @@
{
DEBUG_BLOCK
m_collection->query( "DROP TABLE tracks_temp;" );
+ m_collection->query( "DROP TABLE images_temp;" );
m_collection->query( "DROP TABLE albums_temp;" );
m_collection->query( "DROP TABLE genres_temp;" );
m_collection->query( "DROP TABLE years_temp;" );
@@ -209,6 +221,10 @@
artistIds += artistId;
}
m_collection->insert( QString ( "INSERT INTO artists SELECT * FROM artists_temp WHERE artists_temp.id NOT IN ( %1 );" ).arg( artistIds ), QString() );
+
+ //handle images before albums
+ m_collection->query( "DELETE FROM images;" );
+ m_collection->insert( "INSERT INTO images SELECT * FROM images_temp;", NULL );
QStringList albumIdList = m_collection->query( "SELECT albums.id FROM albums;" );
//in an empty database, albumIdList is empty. This would result in a SQL query like NOT IN ( ) without
@@ -248,7 +264,6 @@
}
m_collection->insert( QString ( "INSERT INTO years SELECT * FROM years_temp WHERE years_temp.id NOT IN ( %1 );" ).arg( yearIds ), QString() );
- //insert( "INSERT INTO images SELECT * FROM images_temp;", NULL );
//insert( "INSERT INTO embed SELECT * FROM embed_temp;", NULL );
//m_collection->insert( "INSERT INTO directories SELECT * FROM directories_temp;", QString() );
//insert( "INSERT INTO uniqueid SELECT * FROM uniqueid_temp;", NULL );
@@ -332,13 +347,22 @@
m_collection->query( "CREATE UNIQUE INDEX artists_name ON artists(name);" );
}
{
+ QString create = "CREATE TABLE images "
+ "(id " + m_collection->idType() +
+ ",path " + m_collection->textColumnType() + " NOT NULL);";
+ m_collection->query( create );
+ m_collection->query( "CREATE UNIQUE INDEX images_name ON images(path);" );
+ }
+ {
QString c = "CREATE TABLE albums "
"(id " + m_collection->idType() +
",name " + m_collection->textColumnType() + " NOT NULL"
- ",artist INTEGER);";
+ ",artist INTEGER" +
+ ",image INTEGER);";
m_collection->query( c );
m_collection->query( "CREATE INDEX albums_name ON albums(name);" );
m_collection->query( "CREATE INDEX albums_artist ON albums(artist);" );
+ m_collection->query( "CREATE INDEX albums_image ON albums(image);" );
m_collection->query( "CREATE UNIQUE INDEX albums_name_artist ON albums(name,artist);" );
//the index below should not be necessary. uncomment if a query plan shows it is
//m_collection->query( "CREATE UNIQUE INDEX albums_artist_name ON albums(artist,name);" );
--- trunk/extragear/multimedia/amarok/src/collection/sqlcollection/ScanManager.cpp #818370:818371
@@ -115,7 +115,7 @@
*m_scanner << dirs;
m_scanner->setOutputChannelMode( KProcess::OnlyStdoutChannel );
connect( m_scanner, SIGNAL( readyReadStandardOutput() ), this, SLOT( slotReadReady() ) );
- connect( m_scanner, SIGNAL( finished( int ) ), SLOT( slotFinished( ) ) );
+ connect( m_scanner, SIGNAL( finished( int ) ), SLOT( slotFinished() ) );
connect( m_scanner, SIGNAL( error( QProcess::ProcessError ) ), SLOT( slotError( QProcess::ProcessError ) ) );
m_scanner->start();
if( m_parser )
@@ -486,6 +486,21 @@
{
//TODO handle playlist
}
+ else if( localname == "image" )
+ {
+ QXmlStreamAttributes attrs = m_reader.attributes();
+ debug() << "Received an image tag: " << attrs.value( "list" ).toString() << " : " << attrs.value( "path" ).toString();
+ // Deserialize CoverBundle list
+ QStringList list = attrs.value( "list" ).toString().split( "AMAROK_MAGIC" );
+ QList< QPair<QString, QString> > covers;
+
+ for( int i = 0; i < list.count(); i += 2 )
+ covers += qMakePair( list[i], list[i + 1] );
+
+ debug() << "Adding image: " << attrs.value( "path" ).toString();
+ processor.addImage( attrs.value( "path" ).toString(), covers );
+ debug() << "Image added!";
+ }
}
}
}
--- trunk/extragear/multimedia/amarok/src/collection/sqlcollection/ScanResultProcessor.cpp #818370:818371
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2007 Maximilian Kossick <maximilian.kossick at googlemail.com>
+ * Copyright (c) 2008 Seb Ruiz <ruiz at kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -81,6 +82,25 @@
}
}
+void
+ScanResultProcessor::addImage( const QString &path, const QList< QPair<QString, QString> > covers )
+{
+ QList< QPair<QString,QString> >::ConstIterator it = covers.begin();
+ for( ; it != covers.end(); it++ )
+ {
+ QPair<QString,QString> key = (*it);
+ if( key.first.isEmpty() || key.second.isEmpty() )
+ continue;
+
+ int artist = artistId( key.first );
+ int album = albumId( key.second, artist );
+
+ // Will automatically add the image path to the database
+ int image = imageId( path, album );
+ debug() << "Added image id " << image << " with path: " << path;
+ }
+}
+
void
ScanResultProcessor::commit()
{
@@ -240,7 +260,6 @@
void
ScanResultProcessor::addTrack( const QVariantMap &trackData, int albumArtistId )
{
-
//amarok 1 stored all tracks of a compilation in different directories.
//when using its "Organize Collection" feature
//try to detect these cases
@@ -380,6 +399,41 @@
}
}
+int
+ScanResultProcessor::imageId( const QString &image, int albumId )
+{
+ DEBUG_BLOCK
+ // assume the album is valid
+ if( albumId < 0 )
+ return -1;
+
+ QPair<QString, int> key( image, albumId );
+ if( m_images.contains( key ) )
+ return m_images.value( key );
+
+ QString query = QString( "SELECT images_temp.id FROM images_temp INNER JOIN albums_temp ON albums_temp.image = images_temp.id WHERE images_temp.path = '%1' AND albums_temp.id = %2;" )
+ .arg( m_collection->escape( image ) ).arg( QString::number( albumId ) );
+ QStringList res = m_collection->query( query );
+ if( res.isEmpty() )
+ {
+ QString insert = QString( "INSERT INTO images_temp( path ) VALUES ('%1');" ).arg( m_collection->escape( image ) );
+ int id = m_collection->insert( insert, "images_temp" );
+ m_images.insert( key, id );
+
+ // Make sure the album table is up to date
+ QString update = QString( "UPDATE albums_temp SET image = %1 WHERE id = %2" )
+ .arg( QString::number( id ) ).arg( QString::number( albumId ) );
+ m_collection->query( update );
+ return id;
+ }
+ else
+ {
+ int id = res[0].toInt();
+ m_images.insert( key, id );
+ return id;
+ }
+}
+
int
ScanResultProcessor::albumId( const QString &album, int artistId )
{
--- trunk/extragear/multimedia/amarok/src/collection/sqlcollection/ScanResultProcessor.h #818370:818371
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2007 Maximilian Kossick <maximilian.kossick at googlemail.com>
+ * Copyright (c) 2008 Seb Ruiz <ruiz at kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,7 +31,6 @@
class ScanResultProcessor
{
-
public:
enum ScanType
{
@@ -42,19 +42,20 @@
~ScanResultProcessor();
void addDirectory( const QString &dir, uint mtime );
+ void addImage( const QString &path, const QList< QPair<QString, QString> > );
void setScanType( ScanType type );
void processDirectory( const QList<QVariantMap > &data );
void commit();
void rollback();
private:
-
void addTrack( const QVariantMap &trackData, int albumArtistId );
int artistId( const QString &artist );
int genreId( const QString &genre );
int composerId( const QString &composer );
int yearId( const QString &year );
+ int imageId( const QString &image, int albumId );
int albumId( const QString &album, int artistId );
int urlId( const QString &url );
int directoryId( const QString &dir );
@@ -73,6 +74,7 @@
QMap<QString, int> m_year;
QMap<QString, int> m_composer;
QMap<QPair<QString, int>, int> m_albums;
+ QMap<QPair<QString, int>, int> m_images;
QMap<QString, int> m_directories;
QHash<QString, uint> m_filesInDirs;
More information about the Amarok-devel
mailing list