1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-07-30 19:00:12 +02:00

Added discnumber & composer to the DB schema and sorting by discnumber.

Added support for three new metadata elements of a track: Album Artist,
Composer and Disc Number. Since these are not supported in ID3v1 which
TagLib uses as common ground between the different metadata formats, I
had to handle the following cases separately: APE, ASF, ID3v1, ID3v2,
MP4 and OGG.
Modified the DB schema to include composer and discnumber. Provided the
dbmigrate file and bumped the schema version.
Added composer and discnumber data to all relevant queries.
Removed a bogus result->setYear from some queries in dbcmd_resolve.cpp.
This commit is contained in:
Teo Mrnjavac
2011-11-11 19:20:02 +01:00
committed by Dominik Schmidt
parent 68b146e560
commit 4e59f1dc12
33 changed files with 995 additions and 96 deletions

View File

@@ -1,4 +1,4 @@
-- Script to migate from db version 6 to 27
-- Script to migate from db version 26 to 27
-- Nothing to do
CREATE TABLE IF NOT EXISTS collection_attributes (

View File

@@ -0,0 +1,7 @@
-- Script to migate from db version 27 to 28.
-- Added albumartist and discnumber to file_join
ALTER TABLE file_join ADD COLUMN composer INTEGER REFERENCES artist(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE file_join ADD COLUMN discnumber INTEGER;
UPDATE settings SET v = '28' WHERE k == 'schema_version';

View File

@@ -133,5 +133,6 @@
<file>data/images/headphones-bigger.png</file>
<file>data/images/no-album-no-case.png</file>
<file>data/images/rdio.png</file>
<file>data/sql/dbmigrate-27_to_28.sql</file>
</qresource>
</RCC>

View File

@@ -97,11 +97,29 @@ set( libGuiSources
playlist/topbar/searchbutton.cpp
ExternalResolverGui.cpp
network/bufferiodevice.cpp
network/msgprocessor.cpp
network/streamconnection.cpp
network/dbsyncconnection.cpp
network/remotecollection.cpp
network/portfwdthread.cpp
network/servent.cpp
network/connection.cpp
network/controlconnection.cpp
resolvers/scriptresolver.cpp
resolvers/qtscriptresolver.cpp
sip/SipModel.cpp
taghandlers/tag.cpp
taghandlers/apetag.cpp
taghandlers/asftag.cpp
taghandlers/id3v1tag.cpp
taghandlers/id3v2tag.cpp
taghandlers/mp4tag.cpp
taghandlers/oggtag.cpp
utils/widgetdragfilter.cpp
utils/xspfgenerator.cpp
utils/jspfloader.cpp
@@ -537,6 +555,14 @@ set( libHeaders
set( libHeaders_NoMOC
infosystem/infoplugins/unix/imageconverter.h
taghandlers/tag.h
taghandlers/apetag.h
taghandlers/asftag.h
taghandlers/id3v1tag.h
taghandlers/id3v2tag.h
taghandlers/mp4tag.h
taghandlers/oggtag.h
utils/tomahawkutils.h
)

View File

@@ -80,7 +80,7 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
TomahawkSqlQuery query_trackattr = dbi->newquery();
query_file.prepare( "INSERT INTO file(source, url, size, mtime, md5, mimetype, duration, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)" );
query_filejoin.prepare( "INSERT INTO file_join(file, artist, album, track, albumpos) VALUES (?, ?, ?, ?, ?)" );
query_filejoin.prepare( "INSERT INTO file_join(file, artist, album, track, albumpos, composer, discnumber) VALUES (?, ?, ?, ?, ?, ?, ?)" );
query_trackattr.prepare( "INSERT INTO track_attributes(id, k, v) VALUES (?, ?, ?)" );
int added = 0;
@@ -105,8 +105,14 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
QString album = m.value( "album" ).toString();
QString track = m.value( "track" ).toString();
uint albumpos = m.value( "albumpos" ).toUInt();
QString composer = m.value( "composer" ).toString();
uint discnumber = m.value( "discnumber" ).toUInt();
int year = m.value( "year" ).toInt();
int fileid = 0, artistid = 0, albumid = 0, trackid = 0, composerid = 0;
query_file_del.bindValue( 0, url );
query_file_del.exec();
query_file.bindValue( 0, srcid );
query_file.bindValue( 1, url );
query_file.bindValue( 2, size );
@@ -134,13 +140,24 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
continue;
albumid = dbi->albumId( artistid, album, true );
if( !composer.trimmed().isEmpty() )
composerid = dbi->artistId( composer, true );
/*if( composerid < 1 )
continue;*/
// Now add the association
query_filejoin.bindValue( 0, fileid );
query_filejoin.bindValue( 1, artistid );
query_filejoin.bindValue( 2, albumid > 0 ? albumid : QVariant( QVariant::Int ) );
query_filejoin.bindValue( 3, trackid );
query_filejoin.bindValue( 4, albumpos );
query_filejoin.exec();
query_filejoin.bindValue( 5, composerid );
query_filejoin.bindValue( 6, discnumber );
if ( !query_filejoin.exec() )
{
qDebug() << "Error inserting into file_join table";
continue;
}
query_trackattr.bindValue( 0, trackid );
query_trackattr.bindValue( 1, "releaseyear" );

View File

@@ -40,7 +40,7 @@ DatabaseCommand_AllTracks::exec( DatabaseImpl* dbi )
break;
case Album:
m_orderToken = "album.name, file_join.albumpos";
m_orderToken = "album.name, file_join.discnumber, file_join.albumpos";
break;
case ModificationTime:
@@ -48,7 +48,7 @@ DatabaseCommand_AllTracks::exec( DatabaseImpl* dbi )
break;
case AlbumPosition:
m_orderToken = "file_join.albumpos";
m_orderToken = "file_join.discnumber, file_join.albumpos";
break;
}
@@ -68,11 +68,15 @@ DatabaseCommand_AllTracks::exec( DatabaseImpl* dbi )
}
QString sql = QString(
"SELECT file.id, artist.name, album.name, track.name, file.size, "
"file.duration, file.bitrate, file.url, file.source, file.mtime, file.mimetype, file_join.albumpos, artist.id, album.id, track.id "
"SELECT file.id, artist.name, album.name, track.name, composer.name, file.size, " //0
"file.duration, file.bitrate, file.url, file.source, file.mtime, " //6
"file.mimetype, file_join.discnumber, file_join.albumpos, artist.id, " //11
"album.id, track.id, composer.id " //15
"FROM file, artist, track, file_join "
"LEFT OUTER JOIN album "
"ON file_join.album = album.id "
"LEFT OUTER JOIN artist AS composer "
"ON file_join.composer = composer.id "
"WHERE file.id = file_join.file "
"AND file_join.artist = artist.id "
"AND file_join.track = track.id "
@@ -92,15 +96,15 @@ DatabaseCommand_AllTracks::exec( DatabaseImpl* dbi )
while( query.next() )
{
Tomahawk::source_ptr s;
QString url = query.value( 7 ).toString();
QString url = query.value( 8 ).toString();
if ( query.value( 8 ).toUInt() == 0 )
if ( query.value( 9 ).toUInt() == 0 )
{
s = SourceList::instance()->getLocal();
}
else
{
s = SourceList::instance()->get( query.value( 8 ).toUInt() );
s = SourceList::instance()->get( query.value( 9 ).toUInt() );
if ( s.isNull() )
{
Q_ASSERT( false );
@@ -110,26 +114,30 @@ DatabaseCommand_AllTracks::exec( DatabaseImpl* dbi )
url = QString( "servent://%1\t%2" ).arg( s->userName() ).arg( url );
}
QString artist, track, album;
QString artist, track, album, composer;
artist = query.value( 1 ).toString();
album = query.value( 2 ).toString();
track = query.value( 3 ).toString();
composer = query.value( 4 ).toString();
Tomahawk::result_ptr result = Tomahawk::Result::get( url );
Tomahawk::query_ptr qry = Tomahawk::Query::get( artist, track, album );
Tomahawk::artist_ptr artistptr = Tomahawk::Artist::get( query.value( 12 ).toUInt(), artist );
Tomahawk::album_ptr albumptr = Tomahawk::Album::get( query.value( 13 ).toUInt(), album, artistptr );
Tomahawk::artist_ptr artistptr = Tomahawk::Artist::get( query.value( 14 ).toUInt(), artist );
Tomahawk::artist_ptr composerptr = Tomahawk::Artist::get( query.value( 17 ).toUInt(), composer );
Tomahawk::album_ptr albumptr = Tomahawk::Album::get( query.value( 15 ).toUInt(), album, artistptr );
result->setTrackId( query.value( 14 ).toUInt() );
result->setTrackId( query.value( 16 ).toUInt() );
result->setArtist( artistptr );
result->setAlbum( albumptr );
result->setTrack( query.value( 3 ).toString() );
result->setSize( query.value( 4 ).toUInt() );
result->setDuration( query.value( 5 ).toUInt() );
result->setBitrate( query.value( 6 ).toUInt() );
result->setModificationTime( query.value( 9 ).toUInt() );
result->setMimetype( query.value( 10 ).toString() );
result->setAlbumPos( query.value( 11 ).toUInt() );
result->setComposer( composerptr );
result->setSize( query.value( 5 ).toUInt() );
result->setDuration( query.value( 6 ).toUInt() );
result->setBitrate( query.value( 7 ).toUInt() );
result->setModificationTime( query.value( 10 ).toUInt() );
result->setMimetype( query.value( 11 ).toString() );
result->setDiscNumber( query.value( 12 ).toUInt() );
result->setAlbumPos( query.value( 13 ).toUInt() );
result->setScore( 1.0 );
result->setCollection( s->collection() );

View File

@@ -100,16 +100,21 @@ DatabaseCommand_Resolve::resolve( DatabaseImpl* lib )
QString trksToken = QString( "file_join.track IN (%1)" ).arg( trksl.join( "," ) );
QString sql = QString( "SELECT "
"url, mtime, size, md5, mimetype, duration, bitrate, file_join.artist, file_join.album, file_join.track, "
"artist.name as artname, "
"album.name as albname, "
"track.name as trkname, "
"file.source, "
"file_join.albumpos, "
"artist.id as artid, "
"album.id as albid "
"url, mtime, size, md5, mimetype, duration, bitrate, " //0
"file_join.artist, file_join.album, file_join.track, " //7
"file_join.composer, file_join.discnumber, " //10
"artist.name as artname, " //12
"album.name as albname, " //13
"track.name as trkname, " //14
"composer.name as cmpname, " //15
"file.source, " //16
"file_join.albumpos, " //17
"artist.id as artid, " //18
"album.id as albid, " //19
"composer.id as cmpid " //20
"FROM file, file_join, artist, track "
"LEFT JOIN album ON album.id = file_join.album "
"LEFT JOIN artist AS composer ON composer.id = file_join.composer "
"WHERE "
"artist.id = file_join.artist AND "
"track.id = file_join.track AND "
@@ -126,16 +131,16 @@ DatabaseCommand_Resolve::resolve( DatabaseImpl* lib )
source_ptr s;
QString url = files_query.value( 0 ).toString();
if ( files_query.value( 13 ).toUInt() == 0 )
if ( files_query.value( 16 ).toUInt() == 0 )
{
s = SourceList::instance()->getLocal();
}
else
{
s = SourceList::instance()->get( files_query.value( 13 ).toUInt() );
s = SourceList::instance()->get( files_query.value( 16 ).toUInt() );
if( s.isNull() )
{
qDebug() << "Could not find source" << files_query.value( 13 ).toUInt();
qDebug() << "Could not find source" << files_query.value( 16 ).toUInt();
continue;
}
@@ -143,8 +148,12 @@ DatabaseCommand_Resolve::resolve( DatabaseImpl* lib )
}
Tomahawk::result_ptr result = Tomahawk::Result::get( url );
Tomahawk::artist_ptr artist = Tomahawk::Artist::get( files_query.value( 15 ).toUInt(), files_query.value( 10 ).toString() );
Tomahawk::album_ptr album = Tomahawk::Album::get( files_query.value( 16 ).toUInt(), files_query.value( 11 ).toString(), artist );
Tomahawk::artist_ptr artist =
Tomahawk::Artist::get( files_query.value( 18 ).toUInt(), files_query.value( 12 ).toString() );
Tomahawk::album_ptr album =
Tomahawk::Album::get( files_query.value( 19 ).toUInt(), files_query.value( 13 ).toString(), artist );
Tomahawk::artist_ptr composer =
Tomahawk::Artist::get( files_query.value( 20 ).toUInt(), files_query.value( 15 ).toString() );
result->setModificationTime( files_query.value( 1 ).toUInt() );
result->setSize( files_query.value( 2 ).toUInt() );
@@ -152,10 +161,12 @@ DatabaseCommand_Resolve::resolve( DatabaseImpl* lib )
result->setDuration( files_query.value( 5 ).toUInt() );
result->setBitrate( files_query.value( 6 ).toUInt() );
result->setArtist( artist );
result->setComposer( composer );
result->setAlbum( album );
result->setTrack( files_query.value( 12 ).toString() );
result->setDiscNumber( files_query.value( 11 ).toUInt() );
result->setTrack( files_query.value( 14 ).toString() );
result->setRID( uuid() );
result->setAlbumPos( files_query.value( 14 ).toUInt() );
result->setAlbumPos( files_query.value( 17 ).toUInt() );
result->setTrackId( files_query.value( 9 ).toUInt() );
TomahawkSqlQuery attrQuery = lib->newquery();
@@ -248,16 +259,21 @@ DatabaseCommand_Resolve::fullTextResolve( DatabaseImpl* lib )
QString albsToken = QString( "file_join.album IN (%1)" ).arg( albsl.join( "," ) );
QString sql = QString( "SELECT "
"url, mtime, size, md5, mimetype, duration, bitrate, file_join.artist, file_join.album, file_join.track, "
"artist.name as artname, "
"album.name as albname, "
"track.name as trkname, "
"file.source, "
"file_join.albumpos, "
"artist.id as artid, "
"album.id as albid "
"url, mtime, size, md5, mimetype, duration, bitrate, " //0
"file_join.artist, file_join.album, file_join.track, " //7
"file_join.composer, file_join.discnumber, " //10
"artist.name as artname, " //12
"album.name as albname, " //13
"track.name as trkname, " //14
"composer.name as cmpname, " //15
"file.source, " //16
"file_join.albumpos, " //17
"artist.id as artid, " //18
"album.id as albid, " //19
"composer.id as cmpid " //20
"FROM file, file_join, artist, track "
"LEFT JOIN album ON album.id = file_join.album "
"LEFT JOIN artist AS composer ON composer.id = file_join.composer "
"WHERE "
"artist.id = file_join.artist AND "
"track.id = file_join.track AND "
@@ -273,16 +289,16 @@ DatabaseCommand_Resolve::fullTextResolve( DatabaseImpl* lib )
source_ptr s;
QString url = files_query.value( 0 ).toString();
if ( files_query.value( 13 ).toUInt() == 0 )
if ( files_query.value( 16 ).toUInt() == 0 )
{
s = SourceList::instance()->getLocal();
}
else
{
s = SourceList::instance()->get( files_query.value( 13 ).toUInt() );
s = SourceList::instance()->get( files_query.value( 16 ).toUInt() );
if( s.isNull() )
{
qDebug() << "Could not find source" << files_query.value( 13 ).toUInt();
qDebug() << "Could not find source" << files_query.value( 16 ).toUInt();
continue;
}
@@ -290,8 +306,12 @@ DatabaseCommand_Resolve::fullTextResolve( DatabaseImpl* lib )
}
Tomahawk::result_ptr result = Tomahawk::Result::get( url );
Tomahawk::artist_ptr artist = Tomahawk::Artist::get( files_query.value( 15 ).toUInt(), files_query.value( 10 ).toString() );
Tomahawk::album_ptr album = Tomahawk::Album::get( files_query.value( 16 ).toUInt(), files_query.value( 11 ).toString(), artist );
Tomahawk::artist_ptr artist =
Tomahawk::Artist::get( files_query.value( 18 ).toUInt(), files_query.value( 12 ).toString() );
Tomahawk::album_ptr album =
Tomahawk::Album::get( files_query.value( 19 ).toUInt(), files_query.value( 13 ).toString(), artist );
Tomahawk::artist_ptr composer =
Tomahawk::Artist::get( files_query.value( 20 ).toUInt(), files_query.value( 15 ).toString() );
result->setModificationTime( files_query.value( 1 ).toUInt() );
result->setSize( files_query.value( 2 ).toUInt() );
@@ -299,12 +319,13 @@ DatabaseCommand_Resolve::fullTextResolve( DatabaseImpl* lib )
result->setDuration( files_query.value( 5 ).toUInt() );
result->setBitrate( files_query.value( 6 ).toUInt() );
result->setArtist( artist );
result->setComposer( composer );
result->setAlbum( album );
result->setTrack( files_query.value( 12 ).toString() );
result->setDiscNumber( files_query.value( 11 ).toUInt() );
result->setTrack( files_query.value( 14 ).toString() );
result->setRID( uuid() );
result->setAlbumPos( files_query.value( 14 ).toUInt() );
result->setAlbumPos( files_query.value( 17 ).toUInt() );
result->setTrackId( files_query.value( 9 ).toUInt() );
result->setYear( files_query.value( 17 ).toUInt() );
for ( int k = 0; k < trackPairs.count(); k++ )
{

View File

@@ -40,7 +40,7 @@
*/
#include "schema.sql.h"
#define CURRENT_SCHEMA_VERSION 27
#define CURRENT_SCHEMA_VERSION 28
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
@@ -208,10 +208,11 @@ DatabaseImpl::file( int fid )
Tomahawk::result_ptr r;
TomahawkSqlQuery query = newquery();
query.exec( QString( "SELECT url, mtime, size, md5, mimetype, duration, bitrate, "
"file_join.artist, file_join.album, file_join.track, "
"file_join.artist, file_join.album, file_join.track, file_join.composer "
"(select name from artist where id = file_join.artist) as artname, "
"(select name from album where id = file_join.album) as albname, "
"(select name from track where id = file_join.track) as trkname, "
"(select name from artist where id = file_join.composer) as cmpname, "
"source "
"FROM file, file_join "
"WHERE file.id = file_join.file AND file.id = %1" )
@@ -222,13 +223,13 @@ DatabaseImpl::file( int fid )
Tomahawk::source_ptr s;
QString url = query.value( 0 ).toString();
if ( query.value( 13 ).toUInt() == 0 )
if ( query.value( 15 ).toUInt() == 0 )
{
s = SourceList::instance()->getLocal();
}
else
{
s = SourceList::instance()->get( query.value( 13 ).toUInt() );
s = SourceList::instance()->get( query.value( 15 ).toUInt() );
if ( s.isNull() )
{
return r;
@@ -238,8 +239,9 @@ DatabaseImpl::file( int fid )
}
r = Tomahawk::Result::get( url );
Tomahawk::artist_ptr artist = Tomahawk::Artist::get( query.value( 7 ).toUInt(), query.value( 10 ).toString() );
Tomahawk::album_ptr album = Tomahawk::Album::get( query.value( 8 ).toUInt(), query.value( 11 ).toString(), artist );
Tomahawk::artist_ptr artist = Tomahawk::Artist::get( query.value( 7 ).toUInt(), query.value( 11 ).toString() );
Tomahawk::album_ptr album = Tomahawk::Album::get( query.value( 8 ).toUInt(), query.value( 12 ).toString(), artist );
Tomahawk::artist_ptr composer = Tomahawk::Artist::get( query.value( 10 ).toUInt(), query.value( 14 ).toString() );
r->setModificationTime( query.value( 1 ).toUInt() );
r->setSize( query.value( 2 ).toUInt() );
@@ -248,7 +250,8 @@ DatabaseImpl::file( int fid )
r->setBitrate( query.value( 6 ).toUInt() );
r->setArtist( artist );
r->setAlbum( album );
r->setTrack( query.value( 12 ).toString() );
r->setComposer( composer );
r->setTrack( query.value( 13 ).toString() );
r->setTrackId( query.value( 9 ).toUInt() );
r->setCollection( s->collection() );
r->setScore( 1.0 );
@@ -557,17 +560,22 @@ DatabaseImpl::resultFromHint( const Tomahawk::query_ptr& origquery )
bool searchlocal = s->isLocal();
QString sql = QString( "SELECT "
"url, mtime, size, md5, mimetype, duration, bitrate, file_join.artist, file_join.album, file_join.track, "
"artist.name as artname, "
"album.name as albname, "
"track.name as trkname, "
"file.source, "
"file_join.albumpos, "
"artist.id as artid, "
"album.id as albid, "
"track_attributes.v as year "
"url, mtime, size, md5, mimetype, duration, bitrate, " //0
"file_join.artist, file_join.album, file_join.track, " //7
"file_join.composer, " //10
"artist.name as artname, " //11
"album.name as albname, " //12
"track.name as trkname, " //13
"composer.name as cmpname, " //14
"file.source, " //15
"file_join.albumpos, " //16
"artist.id as artid, " //17
"album.id as albid, " //18
"composer.id as cmpid, " //19
"track_attributes.v as year " //20
"FROM file, file_join, artist, track, track_attributes "
"LEFT JOIN album ON album.id = file_join.album "
"LEFT JOIN artist AS composer on composer.id = file_join.composer "
"WHERE "
"artist.id = file_join.artist AND "
"track.id = file_join.track AND "
@@ -586,13 +594,13 @@ DatabaseImpl::resultFromHint( const Tomahawk::query_ptr& origquery )
Tomahawk::source_ptr s;
QString url = query.value( 0 ).toString();
if ( query.value( 13 ).toUInt() == 0 )
if ( query.value( 15 ).toUInt() == 0 )
{
s = SourceList::instance()->getLocal();
}
else
{
s = SourceList::instance()->get( query.value( 13 ).toUInt() );
s = SourceList::instance()->get( query.value( 15 ).toUInt() );
if ( s.isNull() )
{
return res;
@@ -602,8 +610,9 @@ DatabaseImpl::resultFromHint( const Tomahawk::query_ptr& origquery )
}
res = Tomahawk::Result::get( url );
Tomahawk::artist_ptr artist = Tomahawk::Artist::get( query.value( 15 ).toUInt(), query.value( 10 ).toString() );
Tomahawk::album_ptr album = Tomahawk::Album::get( query.value( 16 ).toUInt(), query.value( 11 ).toString(), artist );
Tomahawk::artist_ptr artist = Tomahawk::Artist::get( query.value( 17 ).toUInt(), query.value( 11 ).toString() );
Tomahawk::album_ptr album = Tomahawk::Album::get( query.value( 18 ).toUInt(), query.value( 12 ).toString(), artist );
Tomahawk::artist_ptr composer = Tomahawk::Artist::get( query.value( 19 ).toUInt(), query.value( 14 ).toString() );
res->setModificationTime( query.value( 1 ).toUInt() );
res->setSize( query.value( 2 ).toUInt() );
@@ -612,13 +621,14 @@ DatabaseImpl::resultFromHint( const Tomahawk::query_ptr& origquery )
res->setBitrate( query.value( 6 ).toInt() );
res->setArtist( artist );
res->setAlbum( album );
res->setComposer( composer );
res->setScore( 1.0 );
res->setTrack( query.value( 12 ).toString() );
res->setAlbumPos( query.value( 14 ).toUInt() );
res->setTrack( query.value( 13 ).toString() );
res->setAlbumPos( query.value( 16 ).toUInt() );
res->setRID( uuid() );
res->setTrackId( query.value( 9 ).toUInt() );
res->setCollection( s->collection() );
res->setYear( query.value( 17 ).toUInt() );
res->setYear( query.value( 20 ).toUInt() );
}
return res;

View File

@@ -52,7 +52,7 @@ public:
TomahawkSqlQuery newquery() { return TomahawkSqlQuery( m_db ); }
QSqlDatabase& database() { return m_db; }
int artistId( const QString& name_orig, bool autoCreate );
int artistId( const QString& name_orig, bool autoCreate ); //also for composers!
int trackId( int artistid, const QString& name_orig, bool autoCreate );
int albumId( int artistid, const QString& name_orig, bool autoCreate );

View File

@@ -175,7 +175,9 @@ CREATE TABLE IF NOT EXISTS file_join (
artist INTEGER NOT NULL REFERENCES artist(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
track INTEGER NOT NULL REFERENCES track(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
album INTEGER REFERENCES album(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
albumpos INTEGER
albumpos INTEGER,
composer INTEGER REFERENCES artist(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
discnumber INTEGER
);
CREATE INDEX file_join_track ON file_join(track);
CREATE INDEX file_join_artist ON file_join(artist);
@@ -292,4 +294,4 @@ CREATE TABLE IF NOT EXISTS settings (
v TEXT NOT NULL DEFAULT ''
);
INSERT INTO settings(k,v) VALUES('schema_version', '27');
INSERT INTO settings(k,v) VALUES('schema_version', '28');

View File

@@ -1,5 +1,5 @@
/*
This file was automatically generated from schema.sql on Wed Nov 16 22:47:16 EST 2011.
This file was automatically generated from ./schema.sql on Fri Nov 18 14:00:37 CET 2011.
*/
static const char * tomahawk_schema_sql =
@@ -116,7 +116,9 @@ static const char * tomahawk_schema_sql =
" artist INTEGER NOT NULL REFERENCES artist(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,"
" track INTEGER NOT NULL REFERENCES track(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,"
" album INTEGER REFERENCES album(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,"
" albumpos INTEGER"
" albumpos INTEGER,"
" composer INTEGER REFERENCES artist(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,"
" discnumber INTEGER"
");"
"CREATE INDEX file_join_track ON file_join(track);"
"CREATE INDEX file_join_artist ON file_join(artist);"
@@ -189,7 +191,7 @@ static const char * tomahawk_schema_sql =
" k TEXT NOT NULL PRIMARY KEY,"
" v TEXT NOT NULL DEFAULT ''"
");"
"INSERT INTO settings(k,v) VALUES('schema_version', '27');"
"INSERT INTO settings(k,v) VALUES('schema_version', '28');"
;
const char * get_tomahawk_sql()

View File

@@ -177,6 +177,7 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c
QString track1 = q1->track();
QString track2 = q2->track();
unsigned int albumpos1 = 0, albumpos2 = 0;
unsigned int discnumber1 = 0, discnumber2 = 0;
unsigned int bitrate1 = 0, bitrate2 = 0;
unsigned int mtime1 = 0, mtime2 = 0;
unsigned int size1 = 0, size2 = 0;
@@ -189,6 +190,7 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c
album1 = r->album()->name();
track1 = r->track();
albumpos1 = r->albumpos();
discnumber1 = r->discnumber();
bitrate1 = r->bitrate();
mtime1 = r->modificationTime();
id1 = r->trackId();
@@ -201,6 +203,7 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c
album2 = r->album()->name();
track2 = r->track();
albumpos2 = r->albumpos();
discnumber2 = r->discnumber();
bitrate2 = r->bitrate();
mtime2 = r->modificationTime();
id2 = r->trackId();
@@ -220,10 +223,15 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c
{
if ( album1 == album2 )
{
if ( albumpos1 == albumpos2 )
return id1 < id2;
if( discnumber1 == discnumber2 )
{
if ( albumpos1 == albumpos2 )
return id1 < id2;
return albumpos1 < albumpos2;
return albumpos1 < albumpos2;
}
return discnumber1 < discnumber2;
}
return QString::localeAwareCompare( album1, album2 ) < 0;
@@ -235,10 +243,15 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c
{
if ( album1 == album2 )
{
if ( albumpos1 == albumpos2 )
return id1 < id2;
if( discnumber1 == discnumber2 )
{
if ( albumpos1 == albumpos2 )
return id1 < id2;
return albumpos1 < albumpos2;
return albumpos1 < albumpos2;
}
return discnumber1 < discnumber2;
}
return QString::localeAwareCompare( album1, album2 ) < 0;

View File

@@ -894,6 +894,11 @@ TreeModel::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QV
QStringList tracks = returnedData[ "tracks" ].toStringList();
QList<query_ptr> ql;
//TODO: Figure out how to do this with a multi-disk album without breaking the
// current behaviour. I just know too little about InfoSystem to deal with
// it right now, I've only taken the liberty of adding Query::setDiscNumber
// which should make this easier. --Teo 11/2011
unsigned int trackNo = 1;
foreach ( const QString& trackName, tracks )

View File

@@ -286,20 +286,39 @@ TreeProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) co
unsigned int albumpos1 = 0;
unsigned int albumpos2 = 0;
if ( !p1->query().isNull() )
unsigned int discnumber1 = 0;
unsigned int discnumber2 = 0;
if( !p1->query().isNull() )
{
albumpos1 = p1->query()->albumpos();
if ( !p2->query().isNull() )
discnumber1 = p1->query()->discnumber();
}
if( !p2->query().isNull() )
{
albumpos2 = p2->query()->albumpos();
if ( albumpos1 == 0 && !p1->result().isNull() )
discnumber2 = p2->query()->discnumber();
}
if( albumpos1 == 0 && !p1->result().isNull() )
albumpos1 = p1->result()->albumpos();
if ( albumpos2 == 0 && !p2->result().isNull() )
if( discnumber1 == 0 && !p1->result().isNull() )
discnumber1 = p1->result()->discnumber();
if( albumpos2 == 0 && !p2->result().isNull() )
albumpos2 = p2->result()->albumpos();
if( discnumber2 == 0 && !p2->result().isNull() )
discnumber2 = p2->result()->discnumber();
const QString& lefts = textForItem( p1 );
const QString& rights = textForItem( p2 );
if ( albumpos1 != albumpos2 )
return albumpos1 < albumpos2;
if( discnumber1 != discnumber2 )
return discnumber1 < discnumber2;
else
{
if ( albumpos1 != albumpos2 )
return albumpos1 < albumpos2;
}
if ( lefts == rights )
return (qint64)&p1 < (qint64)&p2;

View File

@@ -127,12 +127,14 @@ Query::updateSortNames()
if ( isFullTextQuery() )
{
m_artistSortname = DatabaseImpl::sortname( m_fullTextQuery, true );
m_composerSortName = DatabaseImpl::sortname( m_composer, true );
m_albumSortname = DatabaseImpl::sortname( m_fullTextQuery );
m_trackSortname = m_albumSortname;
}
else
{
m_artistSortname = DatabaseImpl::sortname( m_artist, true );
m_composerSortName = DatabaseImpl::sortname( m_composer, true );
m_albumSortname = DatabaseImpl::sortname( m_album );
m_trackSortname = DatabaseImpl::sortname( m_track );
}

View File

@@ -79,11 +79,13 @@ public:
QList< QWeakPointer< Tomahawk::Resolver > > resolvedBy() const { return m_resolvers; }
void setArtist( const QString& artist ) { m_artist = artist; updateSortNames(); }
void setComposer( const QString& composer ) { m_composer = composer; updateSortNames(); }
void setAlbum( const QString& album ) { m_album = album; updateSortNames(); }
void setTrack( const QString& track ) { m_track = track; updateSortNames(); }
void setResultHint( const QString& resultHint ) { m_resultHint = resultHint; }
void setDuration( int duration ) { m_duration = duration; }
void setAlbumPos( unsigned int albumpos ) { m_albumpos = albumpos; }
void setDiscNumber( unsigned int discnumber ) { m_discnumber = discnumber; }
QVariant toVariant() const;
QString toString() const;
@@ -93,11 +95,13 @@ public:
QString albumSortname() const { return m_albumSortname; }
QString trackSortname() const { return m_trackSortname; }
QString artist() const { return m_artist; }
QString composer() const { return m_composer; }
QString album() const { return m_album; }
QString track() const { return m_track; }
int duration() const { return m_duration; }
unsigned int albumpos() const { return m_albumpos; }
unsigned int discnumber() const { return m_discnumber; }
void setResolveFinished( bool resolved ) { m_resolveFinished = resolved; }
void setPlayedBy( const Tomahawk::source_ptr& source, unsigned int playtime );
@@ -171,16 +175,19 @@ private:
mutable QID m_qid;
QString m_artistSortname;
QString m_composerSortName;
QString m_albumSortname;
QString m_trackSortname;
QString m_artist;
QString m_composer;
QString m_album;
QString m_track;
QString m_fullTextQuery;
int m_duration;
unsigned int m_albumpos;
unsigned int m_discnumber;
QString m_resultHint;
QPair< Tomahawk::source_ptr, unsigned int > m_playedBy;

View File

@@ -58,6 +58,7 @@ Result::Result( const QString& url )
, m_size( 0 )
, m_albumpos( 0 )
, m_modtime( 0 )
, m_discnumber( 0 )
, m_year( 0 )
, m_score( 0 )
, m_trackId( 0 )
@@ -82,6 +83,12 @@ Result::artist() const
return m_artist;
}
artist_ptr
Result::composer() const
{
return m_composer;
}
album_ptr
Result::album() const
@@ -151,6 +158,8 @@ Result::toVariant() const
m.insert( "duration", duration() );
m.insert( "score", score() );
m.insert( "sid", id() );
m.insert( "discnumber", discnumber() );
m.insert( "composer", composer()->name() );
return m;
}
@@ -211,6 +220,13 @@ Result::setArtist( const Tomahawk::artist_ptr& artist )
}
void
Result::setComposer( const Tomahawk::artist_ptr &composer )
{
m_composer = composer;
}
void
Result::setAlbum( const Tomahawk::album_ptr& album )
{

View File

@@ -69,6 +69,7 @@ public:
collection_ptr collection() const;
Tomahawk::artist_ptr artist() const;
Tomahawk::album_ptr album() const;
Tomahawk::artist_ptr composer() const;
QString track() const { return m_track; }
QString url() const { return m_url; }
QString mimetype() const { return m_mimetype; }
@@ -80,6 +81,7 @@ public:
unsigned int albumpos() const { return m_albumpos; }
unsigned int modificationTime() const { return m_modtime; }
int year() const { return m_year; }
unsigned int discnumber() const { return m_discnumber; }
void setScore( float score ) { m_score = score; }
void setTrackId( unsigned int id ) { m_trackId = id; }
@@ -89,6 +91,7 @@ public:
void setFriendlySource( const QString& s ) { m_friendlySource = s; }
void setArtist( const Tomahawk::artist_ptr& artist );
void setAlbum( const Tomahawk::album_ptr& album );
void setComposer( const Tomahawk::artist_ptr& composer );
void setTrack( const QString& track ) { m_track = track; }
void setMimetype( const QString& mimetype ) { m_mimetype = mimetype; }
void setDuration( unsigned int duration ) { m_duration = duration; }
@@ -97,6 +100,7 @@ public:
void setAlbumPos( unsigned int albumpos ) { m_albumpos = albumpos; }
void setModificationTime( unsigned int modtime ) { m_modtime = modtime; }
void setYear( unsigned int year ) { m_year = year; }
void setDiscNumber( unsigned int discnumber ) { m_discnumber = discnumber; }
QVariantMap attributes() const { return m_attributes; }
void setAttributes( const QVariantMap& map ) { m_attributes = map; updateAttributes(); }
@@ -125,6 +129,7 @@ private:
Tomahawk::artist_ptr m_artist;
Tomahawk::album_ptr m_album;
Tomahawk::artist_ptr m_composer;
QString m_track;
QString m_url;
QString m_mimetype;
@@ -135,6 +140,7 @@ private:
unsigned int m_size;
unsigned int m_albumpos;
unsigned int m_modtime;
unsigned int m_discnumber;
int m_year;
float m_score;

View File

@@ -0,0 +1,51 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "apetag.h"
namespace Tomahawk
{
APETag::APETag( TagLib::Tag *tag, TagLib::APE::Tag *apeTag )
: Tag( tag )
, m_apeTag( apeTag )
{
TagLib::APE::ItemListMap map = m_apeTag->itemListMap();
for( TagLib::APE::ItemListMap::ConstIterator it = map.begin();
it != map.end(); ++it )
{
TagLib::String key = it->first;
QString val = TStringToQString( it->second.toString() );
//some of these are not defined in the item key according to the hydrogenaudio wiki
//can I use them anyway? --Teo 11/2011
if( key == TagLib::String( "Album Artist" ) )
{
m_albumArtist = val;
}
else if( key == TagLib::String( "Composer" ) )
{
m_composer = val;
}
else if( key == TagLib::String( "Disc" ) )
{
m_discNumber = processDiscNumber( val );
}
}
}
}

View File

@@ -0,0 +1,43 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef APETAG_H
#define APETAG_H
#include "tag.h"
#include <taglib/apetag.h>
namespace Tomahawk
{
class DLLEXPORT APETag : public Tag
{
public:
APETag( TagLib::Tag *, TagLib::APE::Tag * );
virtual QString albumArtist() const { return m_albumArtist; }
virtual QString composer() const { return m_composer; }
virtual unsigned int discNumber() const { return m_discNumber; }
private:
TagLib::APE::Tag *m_apeTag;
};
}
#endif // APETAG_H

View File

@@ -0,0 +1,49 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "asftag.h"
namespace Tomahawk
{
ASFTag::ASFTag( TagLib::Tag *tag, TagLib::ASF::Tag *asfTag )
: Tag( tag )
, m_asfTag( asfTag )
{
TagLib::ASF::AttributeListMap map = m_asfTag->attributeListMap();
for( TagLib::ASF::AttributeListMap::ConstIterator it = map.begin();
it != map.end(); ++it )
{
TagLib::String key = it->first;
QString val = TStringToQString( it->second[ 0 ].toString() );
if( key == TagLib::String( "WM/AlbumTitle" ) ) //album artist
{
m_albumArtist = val;
}
else if( key == TagLib::String( "WM/Composer" ) )
{
m_composer = val;
}
else if( key == TagLib::String( "WM/PartOfSet" ) )
{
m_discNumber = processDiscNumber( val );
}
}
}
}

View File

@@ -0,0 +1,43 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ASFTAG_H
#define ASFTAG_H
#include "tag.h"
#include <taglib/asftag.h>
namespace Tomahawk
{
class DLLEXPORT ASFTag : public Tag
{
public:
ASFTag( TagLib::Tag *, TagLib::ASF::Tag * );
virtual QString albumArtist() const { return m_albumArtist; }
virtual QString composer() const { return m_composer; }
virtual unsigned int discNumber() const { return m_discNumber; }
private:
TagLib::ASF::Tag *m_asfTag;
};
}
#endif // ASFTAG_H

View File

@@ -0,0 +1,28 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "id3v1tag.h"
namespace Tomahawk
{
ID3v1Tag::ID3v1Tag( TagLib::Tag *tag )
: Tag( tag )
{}
}

View File

@@ -0,0 +1,40 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ID3V1TAG_H
#define ID3V1TAG_H
#include "tag.h"
#include <taglib/id3v1tag.h>
namespace Tomahawk
{
class DLLEXPORT ID3v1Tag : public Tag
{
public:
ID3v1Tag( TagLib::Tag * );
virtual QString albumArtist() const { return QString(); }
virtual QString composer() const { return QString(); }
virtual unsigned int discNumber() const { return 0; }
};
}
#endif // ID3V1TAG_H

View File

@@ -0,0 +1,56 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "id3v2tag.h"
#include <taglib/textidentificationframe.h>
namespace Tomahawk
{
ID3v2Tag::ID3v2Tag( TagLib::Tag *tag, TagLib::ID3v2::Tag *id3v2Tag )
: Tag( tag )
, m_id3v2Tag( id3v2Tag )
{
TagLib::ID3v2::FrameList fList = m_id3v2Tag->frameList();
for( TagLib::ID3v2::FrameList::ConstIterator it = fList.begin();
it != fList.end(); ++it )
{
TagLib::String frameId = TagLib::String( (*it)->frameID() );
TagLib::ID3v2::TextIdentificationFrame *frame =
dynamic_cast< TagLib::ID3v2::TextIdentificationFrame * >( *it );
if( frame )
{
QString val = TStringToQString( frame->fieldList().toString( '\n' ) );
if( frameId == TagLib::String( "TPE2" ) ) //album artist
{
m_albumArtist = val;
}
else if( frameId == TagLib::String( "TCOM" ) ) //composer
{
m_composer = val;
}
else if( frameId == TagLib::String( "TPOS" ) ) //disc number
{
m_discNumber = processDiscNumber( val );
}
}
}
}
}

View File

@@ -0,0 +1,43 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ID3V2TAG_H
#define ID3V2TAG_H
#include "tag.h"
#include <taglib/id3v2tag.h>
namespace Tomahawk
{
class DLLEXPORT ID3v2Tag : public Tag
{
public:
ID3v2Tag( TagLib::Tag *, TagLib::ID3v2::Tag * );
virtual QString albumArtist() const { return m_albumArtist; }
virtual QString composer() const { return m_composer; }
virtual unsigned int discNumber() const { return m_discNumber; }
private:
TagLib::ID3v2::Tag *m_id3v2Tag;
};
}
#endif // ID3V2TAG_H

View File

@@ -0,0 +1,49 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "mp4tag.h"
namespace Tomahawk
{
MP4Tag::MP4Tag( TagLib::Tag *tag, TagLib::MP4::Tag *mp4Tag )
: Tag( tag )
, m_mp4Tag( mp4Tag )
{
TagLib::MP4::ItemListMap map = m_mp4Tag->itemListMap();
for( TagLib::MP4::ItemListMap::ConstIterator it = map.begin();
it != map.end(); ++it )
{
TagLib::String key = it->first;
QString val = TStringToQString( it->second.toStringList().toString( '\n' ) );
if( key == TagLib::String( "aART" ) ) //album artist
{
m_albumArtist = val;
}
else if( key == TagLib::String( "\xA9wrt" ) ) //composer
{
m_composer = val;
}
else if( key == TagLib::String( "disk" ) ) //disk number
{
m_discNumber = processDiscNumber( val );
}
}
}
}

View File

@@ -0,0 +1,42 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MP4TAG_H
#define MP4TAG_H
#include "tag.h"
#include <taglib/mp4tag.h>
namespace Tomahawk
{
class DLLEXPORT MP4Tag : public Tag
{
public:
MP4Tag( TagLib::Tag *, TagLib::MP4::Tag * );
virtual QString albumArtist() const { return m_albumArtist; }
virtual QString composer() const { return m_composer; }
virtual unsigned int discNumber() const { return m_discNumber; }
private:
TagLib::MP4::Tag *m_mp4Tag;
};
}
#endif // MP4TAG_H

View File

@@ -0,0 +1,49 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "oggtag.h"
namespace Tomahawk
{
OggTag::OggTag( TagLib::Tag *tag, TagLib::Ogg::XiphComment *xiphComment )
: Tag( tag )
, m_xiphComment( xiphComment )
{
TagLib::Ogg::FieldListMap map = m_xiphComment->fieldListMap();
for( TagLib::Ogg::FieldListMap::ConstIterator it = map.begin();
it != map.end(); ++it )
{
TagLib::String key = it->first;
QString val = TStringToQString( it->second.toString( '\n' ) );
if( key == TagLib::String( "ALBUMARTIST" ) )
{
m_albumArtist = val;
}
else if( key == TagLib::String( "COMPOSER" ) )
{
m_composer = val;
}
else if( key == TagLib::String( "DISCNUMBER" ) )
{
m_discNumber = processDiscNumber( val );
}
}
}
}

View File

@@ -0,0 +1,43 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OGGTAG_H
#define OGGTAG_H
#include "tag.h"
#include <taglib/xiphcomment.h>
namespace Tomahawk
{
class DLLEXPORT OggTag : public Tag
{
public:
OggTag( TagLib::Tag *, TagLib::Ogg::XiphComment * );
virtual QString albumArtist() const { return m_albumArtist; }
virtual QString composer() const { return m_composer; }
virtual unsigned int discNumber() const { return m_discNumber; }
private:
TagLib::Ogg::XiphComment *m_xiphComment;
};
}
#endif // OGGTAG_H

View File

@@ -0,0 +1,123 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tag.h"
#include "apetag.h"
#include "asftag.h"
#include "id3v1tag.h"
#include "id3v2tag.h"
#include "mp4tag.h"
#include "oggtag.h"
#include <taglib/xiphcomment.h>
#include <taglib/vorbisfile.h>
#include <taglib/oggflacfile.h>
#include <taglib/flacfile.h>
#include <taglib/speexfile.h>
#include <taglib/mpegfile.h>
#include <taglib/mp4file.h>
#include <taglib/mpcfile.h>
#include <taglib/asffile.h>
#include <QStringList>
namespace Tomahawk
{
/*static*/ Tag* Tag::fromFile( const TagLib::FileRef &f )
{
Tag *t = 0;
if( TagLib::Ogg::Vorbis::File *file =
dynamic_cast< TagLib::Ogg::Vorbis::File * >( f.file() ) )
{
if( file->tag() )
t = new OggTag( f.tag(), file->tag() );
}
else if( TagLib::Ogg::FLAC::File *file =
dynamic_cast< TagLib::Ogg::FLAC::File * >( f.file() ) )
{
if( file->tag() )
t = new OggTag( f.tag(), file->tag() );
}
else if( TagLib::Ogg::Speex::File *file =
dynamic_cast< TagLib::Ogg::Speex::File * >( f.file() ) )
{
if( file->tag() )
t = new OggTag( f.tag(), file->tag() );
}
else if( TagLib::FLAC::File *file =
dynamic_cast< TagLib::FLAC::File * >( f.file() ) )
{
if( file->xiphComment() )
t = new OggTag( f.tag(), file->xiphComment() );
else if( file->ID3v2Tag() )
t = new ID3v2Tag( f.tag(), file->ID3v2Tag() );
else if( file->ID3v1Tag() )
t = new ID3v1Tag( f.tag() );
}
else if( TagLib::MPEG::File *file =
dynamic_cast< TagLib::MPEG::File * >( f.file() ) )
{
if( file->ID3v2Tag() )
t = new ID3v2Tag( f.tag(), file->ID3v2Tag() );
else if( file->APETag() )
t = new APETag( f.tag(), file->APETag() );
else if( file->ID3v1Tag() )
t = new ID3v1Tag( f.tag() );
}
else if( TagLib::MP4::File *file =
dynamic_cast< TagLib::MP4::File * >( f.file() ) )
{
if( file->tag() )
t = new MP4Tag( f.tag(), file->tag() );
}
else if( TagLib::MPC::File *file =
dynamic_cast< TagLib::MPC::File * >( f.file() ) )
{
if( file->APETag() )
t = new APETag( f.tag(), file->APETag() );
else if( file->ID3v1Tag() )
t = new ID3v1Tag( f.tag() );
}
else if( TagLib::ASF::File *file =
dynamic_cast< TagLib::ASF::File * >( f.file() ) )
{
if( file->tag() )
t = new ASFTag( f.tag(), file->tag() );
}
return t;
}
unsigned int Tag::processDiscNumber( const QString &s ) const
{
int disc;
if( s.indexOf( '/' ) != -1 )
disc = s.split( '/', QString::SkipEmptyParts ).value( 0 ).toInt();
else if( s.indexOf( ':' ) != -1 )
disc = s.split( '/', QString::SkipEmptyParts ).value( 0 ).toInt();
else
disc = s.toInt();
return disc;
}
}

View File

@@ -0,0 +1,72 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TAG_H
#define TAG_H
#include "dllmacro.h"
#include <QtCore/QString>
#include <taglib/tag.h>
#include <taglib/fileref.h>
namespace Tomahawk
{
class DLLEXPORT Tag
{
public:
static Tag *fromFile( const TagLib::FileRef &f );
//getter-setters for common TagLib items
virtual QString title() const { return TStringToQString( m_tag->title() ).trimmed(); }
virtual QString artist() const { return TStringToQString( m_tag->artist() ).trimmed(); }
virtual QString album() const { return TStringToQString( m_tag->album() ).trimmed(); }
virtual QString comment() const { return TStringToQString( m_tag->comment() ).trimmed(); }
virtual QString genre() const { return TStringToQString( m_tag->genre() ).trimmed(); }
virtual unsigned int year() const { return m_tag->year(); }
virtual unsigned int track() const { return m_tag->track(); }
virtual void setTitle( const QString &s ) { m_tag->setTitle( TagLib::String( s.toUtf8().data(), TagLib::String::UTF8 ) ); }
virtual void setArtist( const QString &s ) { m_tag->setArtist( TagLib::String( s.toUtf8().data(), TagLib::String::UTF8 ) ); }
virtual void setAlbum( const QString &s ) { m_tag->setAlbum( TagLib::String( s.toUtf8().data(), TagLib::String::UTF8 ) ); }
virtual void setComment( const QString &s ) { m_tag->setComment( TagLib::String( s.toUtf8().data(), TagLib::String::UTF8 ) ); }
virtual void setGenre( const QString &s ) { m_tag->setGenre( TagLib::String( s.toUtf8().data(), TagLib::String::UTF8 ) ); }
virtual void setYear( unsigned int i ) { m_tag->setYear( i ); }
virtual void setTrack( unsigned int i ) { m_tag->setTrack( i ); }
virtual bool isEmpty() const { return m_tag->isEmpty(); }
virtual QString albumArtist() const = 0;
virtual QString composer() const = 0;
virtual unsigned int discNumber() const = 0;
//TODO: add support for writing those 3 items with TagLib's addField/setField
protected:
Tag( TagLib::Tag *tag ) : m_tag( tag ) {}
unsigned int processDiscNumber( const QString & ) const;
TagLib::Tag *m_tag;
QString m_albumArtist;
QString m_composer;
unsigned int m_discNumber;
};
}
#endif // TAG_H

View File

@@ -29,6 +29,7 @@
#include "database/databasecommand_collectionstats.h"
#include "database/databasecommand_addfiles.h"
#include "database/databasecommand_deletefiles.h"
#include "taghandlers/tag.h"
#include "utils/logger.h"
@@ -333,7 +334,9 @@ MusicScanner::readFile( const QFileInfo& fi )
int bitrate = 0;
int duration = 0;
TagLib::Tag *tag = f.tag();
Tag *tag = Tag::fromFile( f );
if ( f.audioProperties() )
{
TagLib::AudioProperties *properties = f.audioProperties();
@@ -341,9 +344,9 @@ MusicScanner::readFile( const QFileInfo& fi )
bitrate = properties->bitrate();
}
QString artist = TStringToQString( tag->artist() ).trimmed();
QString album = TStringToQString( tag->album() ).trimmed();
QString track = TStringToQString( tag->title() ).trimmed();
QString artist = tag->artist().trimmed();
QString album = tag->album().trimmed();
QString track = tag->title().trimmed();
if ( artist.isEmpty() || track.isEmpty() )
{
// FIXME: do some clever filename guessing
@@ -367,6 +370,9 @@ MusicScanner::readFile( const QFileInfo& fi )
m["track"] = track;
m["albumpos"] = tag->track();
m["year"] = tag->year();
m["albumartist"] = tag->albumArtist();
m["composer"] = tag->composer();
m["discnumber"] = tag->discNumber();
m["hash"] = ""; // TODO
m_scanned++;