void
ScrobblerAdapter::copyTrackMetadata( lastfm::MutableTrack &to, const Meta::TrackPtr &track )
{
    to.setTitle( track->name() );

    QString artistOrComposer;
    Meta::ComposerPtr composer = track->composer();
    if( m_config->scrobbleComposer() && composer )
        artistOrComposer = composer->name();
    Meta::ArtistPtr artist = track->artist();
    if( artistOrComposer.isEmpty() && artist )
        artistOrComposer = artist->name();
    to.setArtist( artistOrComposer );

    Meta::AlbumPtr album = track->album();
    Meta::ArtistPtr albumArtist;
    if( album )
    {
        to.setAlbum( album->name() );
        albumArtist = album->hasAlbumArtist() ? album->albumArtist() : Meta::ArtistPtr();
    }
    if( albumArtist )
        to.setAlbumArtist( albumArtist->name() );

    to.setDuration( track->length() / 1000 );
    if( track->trackNumber() >= 0 )
        to.setTrackNumber( track->trackNumber() );

    lastfm::Track::Source source = lastfm::Track::Player;
    if( track->type() == "stream/lastfm" )
        source = lastfm::Track::LastFmRadio;
    else if( track->type().startsWith( "stream" ) )
        source = lastfm::Track::NonPersonalisedBroadcast;
    else if( track->collection() && track->collection()->collectionId() != "localCollection" )
        source = lastfm::Track::MediaDevice;
    to.setSource( source );
}
Esempio n. 2
0
QString TrackOrganizer::buildDestination(const QString& format, const Meta::TrackPtr& track) const
{
    // get hold of the shared pointers
    Meta::AlbumPtr album = track->album();
    Meta::ArtistPtr artist = track->artist();
    Meta::ComposerPtr composer = track->composer();
    Meta::ArtistPtr albumArtist = album ? album->albumArtist() : Meta::ArtistPtr();
    Meta::GenrePtr genre = track->genre();
    Meta::YearPtr year = track->year();

    bool isCompilation = album && album->isCompilation();

    QMap<QString, QString> args;
    QString strArtist = artist ? artist->name() : QString();
    QString strAlbumArtist = isCompilation ? i18n( "Various Artists" ) :
        ( albumArtist ? albumArtist->name() : strArtist );

    args["theartist"] = strArtist;
    args["thealbumartist"] = strAlbumArtist;

    if( m_postfixThe )
    {
        Amarok::manipulateThe( strArtist, true );
        Amarok::manipulateThe( strAlbumArtist, true );
    }

    if ( track->trackNumber() )
    {
        QString trackNum = QString("%1").arg( track->trackNumber(), 2, 10, QChar('0') );
        args["track"] = trackNum;
    }
    args["title"] = track->name();
    args["artist"] = strArtist;
    args["composer"] = composer ? composer->name() : QString();
    // if year == 0 then we don't want include it
    QString strYear = year ? year->name() : QString();
    args["year"] = strYear.localeAwareCompare( "0" ) == 0 ? QString() : strYear;
    args["album"] = track->album() ? track->album()->name() : QString();
    args["albumartist"] = strAlbumArtist;
    args["comment"] = track->comment();
    args["genre"] = genre ? genre->name() : QString();
    if( m_targetFileExtension.isEmpty() )
        args["filetype"] = track->type();
    else
        args["filetype"] = m_targetFileExtension;
    QString strFolder = QFileInfo( track->playableUrl().toLocalFile() ).path();
    strFolder = strFolder.mid( commonPrefixLength( m_folderPrefix, strFolder ) );
    args["folder"] = strFolder;
    args["initial"] = strAlbumArtist.mid( 0, 1 ).toUpper(); //artists starting with The are already handled above
    if( track->discNumber() )
        args["discnumber"] = QString::number( track->discNumber() );
    args["collectionroot"] = m_folderPrefix;

    // some additional properties not supported by organize dialog.
    args["rating"] = track->statistics()->rating();
    args["filesize"] = track->filesize();
    args["length"] = track->length() / 1000;

    // Fill up default empty values for StringX formater
    // TODO make this values changeable by user
    args["default_album"]           = i18n( "Unknown album" );
    args["default_albumartist"]     = i18n( "Unknown artist" );
    args["default_artist"]          = args["albumartist"];
    args["default_thealbumartist"]  = args["albumartist"];
    args["default_theartist"]       = args["albumartist"];
    args["default_comment"]         = i18n( "No comments" );
    args["default_composer"]        = i18n( "Unknown composer" );
    args["default_discnumber"]      = i18n( "Unknown disc number" );
    args["default_genre"]           = i18n( "Unknown genre" );
    args["default_title"]           = i18n( "Unknown title" );
    args["default_year"]            = i18n( "Unknown year" );

    foreach( const QString &key, args.keys() )
        if( key != "collectionroot" && key != "folder" )
            args[key] = args[key].replace( '/', '-' );

    Amarok::QStringx formatx( format );
    QString result = formatx.namedOptArgs( args );
    return cleanPath( result );
}
void
TestMetaConstants::testValueForField()
{
    Meta::TrackPtr trackPtr;

    // When track is null, an invalid QVariant is returned
    trackPtr = 0;
    QVERIFY( !valueForField( 0, trackPtr ).isValid() );

    // Set up mock track details and create mock track
    QVariantMap trackData;
    trackData[ Meta::Field::URL ] = KUrl( "file:///test/url" );
    trackData[ Meta::Field::TITLE ] = "test track";
    trackData[ Meta::Field::COMMENT ] = "test comment" ;
    trackData[ Meta::Field::TRACKNUMBER ] = 1;
    trackData[ Meta::Field::DISCNUMBER ] = 1;
    trackData[ Meta::Field::BPM ] = qreal( 1 );
    trackData[ Meta::Field::LENGTH ] = qint64( 1 );
    trackData[ Meta::Field::BITRATE ] = 1;
    trackData[ Meta::Field::SAMPLERATE ] = 1;
    trackData[ Meta::Field::FILESIZE ] = 1;
    trackData[ Meta::Field::SCORE ] = double( 1 );
    trackData[ Meta::Field::RATING ] = 1;
    trackData[ Meta::Field::FIRST_PLAYED ] = QDateTime( QDate( 2012, 1, 1) );
    trackData[ Meta::Field::LAST_PLAYED ] = QDateTime( QDate( 2012, 1, 1) );
    trackData[ Meta::Field::PLAYCOUNT ] = 1;
    trackData[ Meta::Field::UNIQUEID ] = "test uid";

    MetaMock *testTrack = new MetaMock( trackData );

    // Associate track with album, artist, etc.
    MockAlbum *testAlbum = new MockAlbum( "test album" );
    MockArtist *testArtist = new MockArtist( "test artist" );
    MockComposer *testComposer = new MockComposer( "test composer" );
    MockGenre *testGenre = new MockGenre( "test genre" );
    MockYear *testYear = new MockYear( "2012" );
    MockLabel *testLabel1 = new MockLabel( "test label 1");
    MockLabel *testLabel2 = new MockLabel( "test label 2" );
    MockLabel *testLabel3 = new MockLabel( "test label 3" );

    // For valAlbumArtist
    testAlbum->m_albumArtist = testArtist;

    testTrack->m_album = testAlbum;
    testTrack->m_artist = testArtist;
    testTrack->m_composer = testComposer;
    testTrack->m_genre = testGenre;
    testTrack->m_year = testYear;
    testTrack->m_labels << Meta::LabelPtr( testLabel1 )
                        << Meta::LabelPtr( testLabel2 )
                        << Meta::LabelPtr( testLabel3 );

    // Make the track pointer point to the created track
    trackPtr = Meta::TrackPtr( testTrack );

    // Case 0
    QVariant trackValue = valueForField( qint64( 0 ), trackPtr );
    QVERIFY( trackValue.toStringList().contains( trackData.value( Meta::Field::URL ).value<KUrl>().path()
        + trackData.value( Meta::Field::TITLE ).toString()
        + trackData.value( Meta::Field::COMMENT ).toString() ) );
    QVERIFY( trackValue.toStringList().contains( testAlbum->name() ) );
    QVERIFY( trackValue.toStringList().contains( testArtist->name() ) );
    QVERIFY( trackValue.toStringList().contains( testGenre->name() ) );

    // Case Meta::valUrl
    trackValue = valueForField( Meta::valUrl, trackPtr );
    QVERIFY( trackValue.toString() == trackData.value( Meta::Field::URL ).value<KUrl>().path() );

    // Case Meta::valTitle
    trackValue = valueForField( Meta::valTitle, trackPtr );
    QVERIFY( trackValue.toString() == trackData.value( Meta::Field::TITLE ).toString() );

    // Case Meta::valArtist for non-null artist
    trackValue = valueForField( Meta::valArtist, trackPtr );
    QVERIFY( trackValue.toString() == testArtist->name() );

    // Case Meta::valAlbum for non-null album
    trackValue = valueForField( Meta::valAlbum, trackPtr );
    QVERIFY( trackValue.toString() == testAlbum->name() );

    // Case Meta::valComposer for non-null composer
    trackValue = valueForField( Meta::valComposer, trackPtr );
    QVERIFY( trackValue.toString() == testComposer->name() );

    // Case Meta::valGenre for non-null genre
    trackValue = valueForField( Meta::valGenre, trackPtr );
    QVERIFY( trackValue.toString() == testGenre->name() );

    // Case Meta::valYear for non-null year
    trackValue = valueForField( Meta::valYear, trackPtr );
    QVERIFY( trackValue.toInt() == testYear->name().toInt() );

    // Case Meta::valComment
    trackValue = valueForField( Meta::valComment, trackPtr );
    QVERIFY( trackValue.toString() == trackData.value( Meta::Field::COMMENT ).toString() );

    // Case Meta::valTrackNr
    trackValue = valueForField( Meta::valTrackNr, trackPtr );
    QVERIFY( trackValue.toInt() == trackData.value( Meta::Field::TRACKNUMBER ).toInt() );

    // Case Meta::valDiscNr
    trackValue = valueForField( Meta::valDiscNr, trackPtr );
    QVERIFY( trackValue.toInt() == trackData.value( Meta::Field::DISCNUMBER ).toInt() );

    // Case Meta::valBpm
    trackValue = valueForField( Meta::valBpm, trackPtr );
    QVERIFY( trackValue.toDouble() == trackData.value( Meta::Field::BPM ).toDouble() );

    // Case Meta::valLength
    trackValue = valueForField( Meta::valLength, trackPtr );
    QVERIFY( trackValue.toInt() == trackData.value( Meta::Field::LENGTH ).toInt());

    // Case Meta::valBitrate
    trackValue = valueForField( Meta::valBitrate, trackPtr );
    QVERIFY( trackValue.toInt() == trackData.value( Meta::Field::BITRATE ).toInt() );

    // Case Meta::valSamplerate
    trackValue = valueForField( Meta::valSamplerate, trackPtr );
    QVERIFY( trackValue.toInt() == trackData.value( Meta::Field::SAMPLERATE ).toInt() );

    // Case Meta::valFilesize
    trackValue = valueForField( Meta::valFilesize, trackPtr );
    QVERIFY( trackValue.toInt() == trackData.value( Meta::Field::FILESIZE ).toInt() );

    // Case Meta::valFormat
    trackValue = valueForField( Meta::valFormat, trackPtr );
     QVERIFY( trackValue.toInt() == int( Amarok::FileTypeSupport::fileType(trackPtr->type() ) ) );

    // Case Meta::valCreateDate
    trackValue = valueForField( Meta::valCreateDate, trackPtr );
    QVERIFY( trackValue.toDateTime().isNull() );

    // Case Meta::valScore
    trackValue = valueForField( Meta::valScore, trackPtr );
    QVERIFY( trackValue.toInt() == trackData.value( Meta::Field::SCORE ).toInt() );

    // Case Meta::valRating
    trackValue = valueForField( Meta::valRating, trackPtr );
    QVERIFY( trackValue.toInt() == trackData.value( Meta::Field::RATING ).toInt() );

    // Case Meta::valFirstPlayed
    trackValue = valueForField( Meta::valFirstPlayed, trackPtr );
    QVERIFY( trackValue.toDateTime() == trackData.value( Meta::Field::FIRST_PLAYED ).toDateTime() );

    // Case Meta::valLastPlayed
    trackValue = valueForField( Meta::valLastPlayed, trackPtr );
    QVERIFY( trackValue.toDateTime() == trackData.value( Meta::Field::LAST_PLAYED ).toDateTime() );

    // Case Meta::valFilesize
    trackValue = valueForField( Meta::valPlaycount, trackPtr );
    QVERIFY( trackValue.toInt() == trackData.value( Meta::Field::PLAYCOUNT ).toInt() );

    // Case Meta::valUniqueId
    trackValue = valueForField( Meta::valUniqueId, trackPtr );
    QVERIFY( trackValue.toString() == trackData.value( Meta::Field::UNIQUEID ).toString() );

    // Case Meta::valTrackGain
    trackValue = valueForField( Meta::valTrackGain, trackPtr );
    QVERIFY( trackValue.toString() == "track gain" );

    // Case Meta::valTrackGainPeak
    trackValue = valueForField( Meta::valTrackGainPeak, trackPtr );
    QVERIFY( trackValue.toString() == "track gain peak" );

    // Case Meta::valAlbumGainGain
    trackValue = valueForField( Meta::valAlbumGain, trackPtr );
    QVERIFY( trackValue.toString() == "album gain" );

    // Case Meta::valAlbumGain
    trackValue = valueForField( Meta::valAlbumGainPeak, trackPtr );
    QVERIFY( trackValue.toString() == "album gain peak" );

    // Case Meta::valAlbumArtist
    trackValue = valueForField( Meta::valAlbumArtist, trackPtr );
    QVERIFY( trackValue.toString() == testAlbum->albumArtist()->name() );

    // Case Meta::valLabel, order of the label names remains same
    trackValue = valueForField( Meta::valLabel, trackPtr );
    QStringList labelNames;
    labelNames << testLabel1->name() << testLabel2->name() << testLabel3->name();
    QVERIFY( trackValue.toStringList() == labelNames );

    // Case Meta::valModified
    trackValue = valueForField( Meta::valModified, trackPtr );
    QVERIFY( trackValue.toDateTime().isNull() );

    // Default, returns an invalid QVariant
    trackValue = valueForField( qint64( -1 ), trackPtr );
    QVERIFY( !trackValue.isValid() );

    // Cases with null artist, album, etc. where an invalid QVariant is returned
    testAlbum->m_albumArtist = 0;
    testTrack->m_album = 0;
    testTrack->m_artist = 0;
    testTrack->m_composer = 0;
    testTrack->m_genre = 0;
    testTrack->m_year = 0;

    // Case Meta::valArtist for null artist
    trackValue = valueForField( Meta::valArtist, trackPtr );
    QVERIFY( !trackValue.isValid() );

    // Case Meta::valAlbum for null album
    trackValue = valueForField( Meta::valAlbum, trackPtr );
    QVERIFY( !trackValue.isValid() );

    // Case Meta::valComposer for null composer
    trackValue = valueForField( Meta::valComposer, trackPtr );
    QVERIFY( !trackValue.isValid() );

    // Case Meta::valGenre for null genre
    trackValue = valueForField( Meta::valGenre, trackPtr );
    QVERIFY( !trackValue.isValid() );

    // Case Meta::valYear for null year
    trackValue = valueForField( Meta::valYear, trackPtr );
    QVERIFY( !trackValue.isValid() );

    // Case Meta::valAlbumArtist for null album artist
    trackValue = valueForField( Meta::valAlbumArtist, trackPtr );
    QVERIFY( !trackValue.isValid() );
}
Esempio n. 4
0
void
IpodCopyTracksJob::run()
{
    if( !m_coll )
        return;  // destructed behind our back
    float totalSafeCapacity = m_coll.data()->totalCapacity() - m_coll.data()->capacityMargin();
    QByteArray mountPoint = QFile::encodeName( m_coll.data()->mountPoint() );
    QString collectionPrettyName = m_coll.data()->prettyName();

    int trackCount = m_sources.size();
    QString operationText;
    if( m_transcodingConfig.isJustCopy() )
        operationText = i18np( "Transferring one track to %2", "Transferring %1 tracks to %2",
                               trackCount, collectionPrettyName );
    else
        operationText = i18np( "Transcoding one track to %2", "Transcoding %1 tracks to %2",
                               trackCount, collectionPrettyName );
    Amarok::Components::logger()->newProgressOperation( this, operationText, trackCount,
                                                        this, SLOT(abort()) );
    itdb_start_sync( m_coll.data()->m_itdb );

    QMapIterator<Meta::TrackPtr, KUrl> it( m_sources );
    while( it.hasNext() )
    {
        if( m_aborted || !m_coll )
            break;

        it.next();
        Meta::TrackPtr track = it.key();
        KUrl sourceUrl = it.value();
        emit startDuplicateTrackSearch( track );

        // wait for searching to finish:
        m_searchingForDuplicates.acquire( 1 );
        if( m_duplicateTrack )
        {
            trackProcessed( Duplicate, track, m_duplicateTrack );
            continue;
        }

        if( !m_coll )
            break;  // destructed behind our back
        if( m_transcodingConfig.isJustCopy()  // if not copying, we catch big files later
            && track->filesize() > totalSafeCapacity - m_coll.data()->usedCapacity() )
        {
            // this is a best effort check, we do one definite one after the file is copied
            debug() << "Refusing to copy" << track->prettyUrl() << "to iPod: there are only"
                    << totalSafeCapacity - m_coll.data()->usedCapacity() << "free bytes (not"
                    << "counting a safety margin) on iPod and track has" << track->filesize()
                    << "bytes.";
            trackProcessed( ExceededingSafeCapacity, track );
            continue;
        }
        QString fileExtension;
        if( m_transcodingConfig.isJustCopy() )
            fileExtension = track->type();
        else
            fileExtension = Amarok::Components::transcodingController()->format(
                            m_transcodingConfig.encoder() )->fileExtension();
        if( !m_coll.data()->supportedFormats().contains( fileExtension ) )
        {
            m_notPlayableFormats.insert( fileExtension );
            trackProcessed( NotPlayable, track );
            continue;
        }
        QByteArray fakeSrcName( "filename." );  // only for file extension
        fakeSrcName.append( QFile::encodeName( fileExtension ) );

        /* determine destination filename; we cannot use ipodTrack because as it has no itdb
         * (and thus mountpoint) set */
        GError *error = 0;
        gchar *destFilename = itdb_cp_get_dest_filename( 0, mountPoint, fakeSrcName, &error );
        if( error )
        {
            warning() << "Cannot construct iPod track filename:" << error->message;
            g_error_free( error );
            error = 0;
        }
        if( !destFilename )
        {
            trackProcessed( InternalError, track );
            continue;
        }

        // start the physical copying
        KUrl destUrl = KUrl( QFile::decodeName( destFilename ) );
        emit startCopyOrTranscodeJob( sourceUrl, destUrl );

        // wait for copying to finish:
        m_copying.acquire( 1 );
        /* fsync so that progress bar gives correct info and user doesnt remove the iPod
         * prematurely */
        QFile destFile( QFile::decodeName( destFilename ) );
        if( !destFile.exists() )
        {
            debug() << destFile.fileName() << "does not exist even though we thought we copied it to iPod";
            trackProcessed( CopyingFailed, track );
            continue;
        }
        if( !m_coll )
            break;  // destructed behind our back
        if( m_coll.data()->usedCapacity() > totalSafeCapacity )
        {
            debug() << "We exceeded total safe-to-use capacity on iPod (safe-to-use:"
                    << totalSafeCapacity << "B, used:" << m_coll.data()->usedCapacity()
                    << "): removing copied track from iPod";
            destFile.remove();
            trackProcessed( ExceededingSafeCapacity, track );
            continue;
        }
        // fsync needs a file opened for writing, and without Apped it truncates files (?)
        if( !destFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
        {
            warning() << "Cannot open file copied to ipod (for writing):" << destFile.fileName()
                      << ": removing it";
            destFile.remove();
            trackProcessed( InternalError, track );
            continue;
        }
        if( destFile.size() )
        fsync( destFile.handle() ); // should flush all kernel buffers to disk
        destFile.close();

        // create a new track object by copying meta-data from existing one:
        IpodMeta::Track *ipodTrack = new IpodMeta::Track( track );
        // tell the track it has been copied:
        bool accepted = ipodTrack->finalizeCopying( mountPoint, destFilename );
        g_free( destFilename );
        destFilename = 0;
        if( !accepted )
        {
            debug() << "ipodTrack->finalizeCopying( destFilename )  returned false!";
            delete ipodTrack;
            trackProcessed( InternalError, track );
            continue;
        }
        if( !m_transcodingConfig.isJustCopy() )
        {
            // we need to reread some metadata in case the file was transcoded
            Meta::FieldHash fields = Meta::Tag::readTags( destFile.fileName() );
            ipodTrack->setBitrate( fields.value( Meta::valBitrate, 0 ).toInt() );
            ipodTrack->setLength( fields.value( Meta::valLength, 0 ).toLongLong() );
            ipodTrack->setSampleRate( fields.value( Meta::valSamplerate, 0 ).toInt() );
            Amarok::FileType type = Amarok::FileType( fields.value( Meta::valFormat, 0 ).toInt() );
            ipodTrack->setType( Amarok::FileTypeSupport::toString( type ) );
            // we retain ReplayGain, tags etc - these shouldn't change; size is read
            // in finalizeCopying()
        }

        // add the track to collection
        if( !m_coll )
        {
            delete ipodTrack;
            break;  // we were waiting for copying, m_coll may got destoryed
        }
        Meta::TrackPtr newTrack = m_coll.data()->addTrack( ipodTrack );
        if( !newTrack )
        {
            destFile.remove();
            trackProcessed( InternalError, track );
            continue;
        }
        trackProcessed( Success, track, newTrack );
    }

    if( m_coll )
        itdb_stop_sync( m_coll.data()->m_itdb );
    emit endProgressOperation( this );

    int sourceSize = m_sources.size();
    int successCount = m_sourceTrackStatus.count( Success );
    int duplicateCount = m_sourceTrackStatus.count( Duplicate );
    QString transferredText;
    if ( m_transcodingConfig.isJustCopy() )
        transferredText = i18ncp( "%2 is collection name", "Transferred one track to %2.",
                                  "Transferred %1 tracks to %2.", successCount, collectionPrettyName );
    else
        transferredText = i18ncp( "%2 is collection name", "Transcoded one track to %2.",
                                  "Transcoded %1 tracks to %2.", successCount, collectionPrettyName );

    if( successCount == sourceSize )
    {
        Amarok::Components::logger()->shortMessage( transferredText );
    }
    else if( m_aborted )
    {
        QString text = i18np( "Transfer aborted. Managed to transfer one track.",
                              "Transfer aborted. Managed to transfer %1 tracks.",
                              successCount );
        Amarok::Components::logger()->longMessage( text );
    }
    else if( successCount + duplicateCount == sourceSize )
    {
        QString text = i18ncp( "%2 is the 'Transferred 123 tracks to Some collection.' message",
            "%2 One track was already there.", "%2 %1 tracks were already there.",
            duplicateCount, transferredText );
        Amarok::Components::logger()->longMessage( text );
    }
    else
    {
        // somethig more severe failed, notify user using a dialog
        emit displaySorryDialog();
    }
}
Esempio n. 5
0
QVariant Meta::valueForField( qint64 field, Meta::TrackPtr track )
{
    if( !track )
        return QVariant();

    switch( field )
    {
    case 0:
    {
        // that is the simple search for MetaQueryWidget
        QSet<QString> allInfos;
        allInfos += track->playableUrl().path()
            += track->name()
            += track->comment();
        if( track->artist() )
            allInfos += track->artist()->name();
        if( track->album() )
            allInfos += track->album()->name();
        if( track->genre() )
            allInfos += track->genre()->name();

        return QVariant( allInfos.toList() );
    }
    case Meta::valUrl:         return track->playableUrl().path();
    case Meta::valTitle:       return track->name();
    case Meta::valArtist:      return track->artist() ?
                               QVariant(track->artist()->name()) : QVariant();
    case Meta::valAlbum:       return track->album() ?
                               QVariant(track->album()->name()) : QVariant();
    case Meta::valGenre:       return track->genre() ?
                               QVariant(track->genre()->name()) : QVariant();
    case Meta::valComposer:    return track->composer() ?
                               QVariant(track->composer()->name()) : QVariant();
    case Meta::valYear:        return track->year() ?
                               QVariant(track->year()->name().toInt()) : QVariant();
    case Meta::valComment:     return track->comment();
    case Meta::valTrackNr:     return track->trackNumber();
    case Meta::valDiscNr:      return track->discNumber();
    case Meta::valBpm:         return track->bpm();
    case Meta::valLength:      return track->length();
    case Meta::valBitrate:     return track->bitrate();
    case Meta::valSamplerate:  return track->sampleRate();
    case Meta::valFilesize:    return track->filesize();
    case Meta::valFormat:      return int(Amarok::FileTypeSupport::fileType(track->type()));

    case Meta::valCreateDate:  return track->createDate();
    case Meta::valScore:       return track->statistics()->score();
    case Meta::valRating:      return track->statistics()->rating();
    case Meta::valFirstPlayed: return track->statistics()->firstPlayed();
    case Meta::valLastPlayed:  return track->statistics()->lastPlayed();
    case Meta::valPlaycount:   return track->statistics()->playCount();
    case Meta::valUniqueId:    return track->uidUrl();

    // todo
    case Meta::valTrackGain:   return "track gain";
    case Meta::valTrackGainPeak:   return "track gain peak";
    case Meta::valAlbumGain:   return "album gain";
    case Meta::valAlbumGainPeak:   return "album gain peak";

    case Meta::valAlbumArtist: return (track->album() && track->album()->albumArtist()) ?
                               QVariant(track->album()->albumArtist()->name()) : QVariant();
    case Meta::valLabel:
      {
          Meta::LabelList labels = track->labels();
          QStringList strLabels;
          foreach( Meta::LabelPtr label, labels )
              strLabels.append( label->name() );
          return QVariant( strLabels );
      }
    case Meta::valModified:  return track->modifyDate();
    default: return QVariant();
    }
}