[Amarok] Add support for readding orphaned files to iPod da

Alejandro Wainzinger aikawarazuni at gmail.com
Mon Aug 3 08:03:56 CEST 2009


Didn't actually know about Meta::File, I'll look into switching.  I
don't like duplicated code either, but I was looking around for a
replacement for creating a MetaBundle from a Url that reads tags and
didn't find this one.

On Mon, Aug 3, 2009 at 1:18 AM, Seb Ruiz<ruiz at kde.org> wrote:
> Hi Alex,
> Not a fan of this at all - you've practically duplicated the meta data
> reading from Meta::File in here (and it's not complete).
>
> You should be creating a new MetaFile::Track object and reading the
> tags directly from this object. This way you also don't need to link
> against taglib and all that foo. Remember, reusing code is always a
> good thing!
>
> Seb
>
> 2009/8/3 Alejandro Wainzinger <aikawarazuni at gmail.com>:
>> commit cf40cecbe12f69b35683504b5c4068f14eff1194
>> Author:     Alejandro Wainzinger <aikawarazuni at gmail.com>
>> AuthorDate: Sun Aug 2 19:59:07 2009 +0200
>> Commit:     Alejandro Wainzinger <aikawarazuni at gmail.com>
>> CommitDate: Sun Aug 2 19:59:48 2009 +0200
>>
>>    Add support for readding orphaned files to iPod database.  Needs to be threaded, but it works.
>>
>> diff --git a/src/collection/ipodcollection/CMakeLists.txt b/src/collection/ipodcollection/CMakeLists.txt
>> index 64e4485..dd96452 100644
>> --- a/src/collection/ipodcollection/CMakeLists.txt
>> +++ b/src/collection/ipodcollection/CMakeLists.txt
>> @@ -27,7 +27,15 @@ if (IPOD_FOUND AND IPOD_0_7 AND WITH_Ipod)
>>    ${CMAKE_CURRENT_BINARY_DIR}/../..
>>    ${AMAROK_COLLECTION_SUPPORT_DIR}
>>    ${KDE4_INCLUDE_DIR}
>> -   ${QT_INCLUDES} )
>> +   ${QT_INCLUDES}
>> +   ${TAGLIB_INCLUDES}
>> +)
>> +
>> +if ( TAGLIB-EXTRAS_FOUND )
>> +    include_directories( ${include_directories} ${TAGLIB-EXTRAS_INCLUDE_DIR} )
>> +endif ( TAGLIB-EXTRAS_FOUND )
>> +
>> +add_definitions(${TAGLIB_CFLAGS})
>>
>>  ########### set GDK var ################
>>      # Generate config-gdk.h.cmake
>> @@ -56,6 +64,8 @@ if (IPOD_FOUND AND IPOD_0_7 AND WITH_Ipod)
>>         ${KDE4_SOLID_LIBRARY}
>>         ${KDE4_THREADWEAVER_LIBRARIES}
>>         ${QT_QTGUI_LIBRARY}
>> +       ${TAGLIB_LIBRARIES}
>> +       ${TAGLIB-EXTRAS_LIBRARIES}
>>         ${GLIB2_LIBRARIES}
>>         ${GDK_LIBRARIES}
>>         ${IPOD_LIBRARIES}
>> diff --git a/src/collection/ipodcollection/handler/IpodHandler.cpp b/src/collection/ipodcollection/handler/IpodHandler.cpp
>> index dfd0eaf..c5b98ee 100644
>> --- a/src/collection/ipodcollection/handler/IpodHandler.cpp
>> +++ b/src/collection/ipodcollection/handler/IpodHandler.cpp
>> @@ -64,6 +64,32 @@ extern "C" {
>>  #include <QStringList>
>>  #include <QTime>
>>
>> +//Taglib:
>> +#include <apetag.h>
>> +#include <fileref.h>
>> +#include <flacfile.h>
>> +#include <id3v1tag.h>
>> +#include <id3v2tag.h>
>> +#include <mpcfile.h>
>> +#include <mpegfile.h>
>> +#include <oggfile.h>
>> +#include <oggflacfile.h>
>> +#include <speexfile.h>
>> +#include <tlist.h>
>> +#include <tstring.h>
>> +#include <vorbisfile.h>
>> +
>> +#ifdef TAGLIB_EXTRAS_FOUND
>> +#include <mp4file.h>
>> +#include <mp4tag.h>
>> +#include <mp4item.h>
>> +#include <audiblefiletyperesolver.h>
>> +#include <asffiletyperesolver.h>
>> +#include <wavfiletyperesolver.h>
>> +#include <realmediafiletyperesolver.h>
>> +#include <mp4filetyperesolver.h>
>> +#endif
>> +
>>  using namespace Meta;
>>
>>  /// IpodHandler
>> @@ -153,7 +179,6 @@ IpodHandler::init()
>>
>>         QString msg = i18n(  "Media Device: could not find iTunesDB on device mounted at %1. "
>>                              "Should I try to initialize your iPod?" ).arg(  mountPoint() );
>> -
>>         if( KMessageBox::warningContinueCancel( 0, msg, i18n( "Initialize iPod?" ),
>>                                                                       KGuiItem( i18n( "&Initialize" ), "new" ) ) == KMessageBox::Continue )
>>         {
>> @@ -364,7 +389,7 @@ IpodHandler::collectionActions()
>>
>>  #endif
>>
>> -    QAction *staleOrphanedAction = new QAction( KIcon( "media-track-edit-amarok" ), i18n(  "&Stale" ), this );
>> +    QAction *staleOrphanedAction = new QAction( KIcon( "media-track-edit-amarok" ), i18n(  "&Stale and Orphaned" ), this );
>>     staleOrphanedAction->setProperty( "popupdropper_svg_id", "edit" );
>>
>>     connect( staleOrphanedAction, SIGNAL( triggered() ), this, SLOT( slotStaleOrphaned() ) );
>> @@ -413,40 +438,164 @@ IpodHandler::slotStaleOrphaned()
>>     {
>>         Meta::TrackList staletracks = staleTracks();
>>         QStringList staleList;
>> +        m_staletracksremoved = 0;
>> +
>> +        if( staletracks.count() > 0 )
>> +        {
>> +
>> +            foreach( Meta::TrackPtr track, staletracks )
>> +            {
>> +                QString ent;
>> +                QTextStream entry( &ent );
>> +                entry << track->artist()->name()
>> +                        << " - "
>> +                        << track->album()->name()
>> +                        << " - "
>> +                        << track->name();
>> +
>> +                staleList << ent;
>> +            }
>> +
>> +            bool ok = false;
>> +
>> +            QStringList itemList = KInputDialog::getItemList( i18n( "Select Stale Tracks To Delete" ), i18n( "Stale Tracks" ), staleList, staleList, true /*multiple*/, &ok, 0 );
>>
>> -        foreach( Meta::TrackPtr track, staletracks )
>> +            if( ok )
>> +            {
>> +                Meta::TrackList staleToDelete;
>> +                foreach( QString item, itemList )
>> +                {
>> +                    staleToDelete << staletracks[ itemList.indexOf( item ) ];
>> +                }
>> +
>> +                m_staletracksremoved = staleToDelete.count();
>> +                // HACK: do through signals/slots, which is how CollectionLocation
>> +                // does deletion of tracks.  Should create protected method to
>> +                // allow Handlers to delete without hackery.
>> +                connect( this, SIGNAL( removeTracksDone() ), SLOT( slotOrphaned() ) );
>> +                removeTrackListFromDevice( staleToDelete );
>> +            }
>> +
>> +        } // endif staletracks
>> +        else
>>         {
>> -            QString ent;
>> -            QTextStream entry( &ent );
>> -            entry << track->artist()->name()
>> -                    << " - "
>> -                    << track->album()->name()
>> -                    << " - "
>> -                    << track->name();
>> -
>> -            staleList << ent;
>> +            slotOrphaned();
>>         }
>> +    }
>>
>> -        bool ok = false;
>>
>> -        QStringList itemList = KInputDialog::getItemList( i18n( "Select Stale Tracks To Delete" ), i18n( "Stale Tracks" ), staleList, staleList, true /*multiple*/, &ok, 0 );
>> +}
>>
>> -        if( ok )
>> +void
>> +IpodHandler::slotOrphaned()
>> +{
>> +    writeDatabase();
>> +
>> +    const QString msg( i18ncp( "@info", "One stale track removed from the database. Scan for orphaned tracks?",
>> +                                "%1 tracks removed from the database. Scan for orphaned tracks?", m_staletracksremoved ) );
>> +
>> +    const bool init = KMessageBox::warningContinueCancel(0,
>> +                                                         msg,
>> +                                                         i18n("Find Orphaned Tracks") ) == KMessageBox::Continue;
>> +
>> +    if( init )
>> +    {
>> +        QStringList orphanedPaths = orphanedTracks();
>> +        int orphanedadded = 0;
>> +
>> +        if( !orphanedPaths.empty() )
>>         {
>> -            Meta::TrackList staleToDelete;
>> -            foreach( QString item, itemList )
>> +            m_statusbar = The::statusBar()->newProgressOperation( this, i18n( "Adding Orphaned Tracks to iPod Database" ) );
>> +
>> +            m_statusbar->setMaximum( orphanedPaths.count() );
>> +
>> +            connect( this, SIGNAL( incrementProgress() ),
>> +                     The::statusBar(), SLOT( incrementProgress() ), Qt::QueuedConnection );
>> +
>> +            connect( this, SIGNAL( databaseWritten(bool)),
>> +                     this, SLOT( slotDatabaseWritten(bool)), Qt::QueuedConnection );
>> +
>> +            foreach( const QString path, orphanedPaths )
>>             {
>> -                staleToDelete << staletracks[ itemList.indexOf( item ) ];
>> +                QString realPath;
>> +                pathExists( path, &realPath );
>> +                const AttributeHash attributes = readTags( realPath );
>> +
>> +                if( attributes.empty() )
>> +                    continue;
>> +
>> +                debug() << "Found: " << attributes["artist"] << " - " << attributes["title"];
>> +
>> +                // Create new track
>> +
>> +                Meta::MediaDeviceTrackPtr destTrack ( new Meta::MediaDeviceTrack( m_memColl ) );
>> +
>> +                // Create a track struct, associate it to track
>> +
>> +                libCreateTrack( destTrack );
>> +
>> +                // Fill the track struct of the destTrack with info from the track parameter as source
>> +
>> +                libSetTitle( destTrack, attributes["title"] );
>> +                libSetArtist( destTrack, attributes["artist"] );
>> +                libSetAlbum( destTrack, attributes["album"] );
>> +                libSetComment( destTrack, attributes["comment"] );
>> +                libSetGenre( destTrack, attributes["genre"] );
>> +                libSetYear( destTrack, attributes["year"] );
>> +                libSetTrackNumber( destTrack, attributes["track"].toInt() );
>> +
>> +                if( attributes.contains("composer" ) )
>> +                    libSetComposer( destTrack, attributes["composer"] );
>> +                if( attributes.contains("discnumber" ) )
>> +                    libSetDiscNumber( destTrack, attributes["discnumber"].toInt() );
>> +
>> +                //libSetBpm( destTrack, attributes["bpm"] );
>> +                if( attributes.contains("filesize" ) )
>> +                    libSetFileSize( destTrack, attributes["filesize"].toInt() );
>> +
>> +                libSetType( destTrack, attributes["filetype"] );
>> +                //libSetPlayableUrl( destTrack, srcTrack );
>> +
>> +                if( attributes["audioproperties"] == "true" )
>> +                {
>> +                    libSetBitrate( destTrack, attributes["bitrate"].toInt() );
>> +                    libSetLength( destTrack, attributes["length"].toInt() );
>> +                    libSetSamplerate( destTrack, attributes["samplerate"].toInt() );
>> +                }
>> +
>> +                // set up the play url
>> +
>> +                m_itdbtrackhash[ destTrack ]->ipod_path = g_strdup( path.toLatin1() );
>> +
>> +                // Add the track struct into the database
>> +
>> +                addTrackInDB( destTrack );
>> +
>> +                // Inform subclass that a track has been added to the db
>> +
>> +                databaseChanged();
>> +
>> +                // Add the new Meta::MediaDeviceTrackPtr into the device collection
>> +
>> +                // add track to collection
>> +                addMediaDeviceTrackToCollection( destTrack );
>> +
>> +                orphanedadded++;
>> +
>>             }
>> -            // HACK: do through signals/slots, which is how CollectionLocation
>> -            // does deletion of tracks.  Should create protected method to
>> -            // allow Handlers to delete without hackery.
>> -            connect( this, SIGNAL( removeTracksDone() ), SLOT( writeDatabase() ) );
>> -            removeTrackListFromDevice( staleToDelete );
>> -        }
>>
>> -        //QStringList orphanedPaths = orphanedTracks();
>> -    }
>> +            writeDatabase();
>> +
>> +        } // foreach
>> +
>> +        const QString orphmsg( i18ncp( "@info", "One orphaned track added to the database.",
>> +                                   "%1 tracks added to the database.", orphanedadded ) );
>> +
>> +        KMessageBox::information(0,
>> +                                 orphmsg,
>> +                                 i18n("Orphaned Tracks Added") );
>> +    } // init
>> +
>>
>>
>>  }
>> @@ -806,8 +955,8 @@ IpodHandler::writeFirewireGuid()
>>  bool
>>  IpodHandler::pathExists( const QString &ipodPath, QString *realPath )
>>  {
>> -    DEBUG_BLOCK
>> -    debug() << "ipodPath: " << ipodPath;
>> +    //DEBUG_BLOCK
>> +    //debug() << "ipodPath: " << ipodPath;
>>     QDir curDir( mountPoint() );
>>     QString curPath = mountPoint();
>>     QStringList components;
>> @@ -823,7 +972,7 @@ IpodHandler::pathExists( const QString &ipodPath, QString *realPath )
>>     QStringList::iterator it = components.begin();
>>     for( ; it != components.end(); ++it )
>>     {
>> -        debug() << "(*it): " << (*it);
>> +        //debug() << "(*it): " << (*it);
>>         found = false;
>>         for( uint i = 0;i < curDir.count(); i++ )
>>         {
>> @@ -922,8 +1071,7 @@ IpodHandler::writeITunesDB( bool threaded )
>>  QString
>>  IpodHandler::itunesDir(const QString &p) const
>>  {
>> -    // NOTE: a colon was removed from the front since 1.4
>> -    QString base( "iPod_Control" );
>> +    QString base( ":iPod_Control" );
>>     if( m_isMobile )
>>         base = ":iTunes:iTunes_Control";
>>
>> @@ -1094,7 +1242,7 @@ QStringList
>>  IpodHandler::orphanedTracks()
>>  {
>>     DEBUG_BLOCK
>> -    int orph = 0;
>> +
>>     QStringList orphanedTracks;
>>     QString musicpath;
>>     if (!pathExists( itunesDir( "Music" ), &musicpath ))
>> @@ -1122,16 +1270,231 @@ IpodHandler::orphanedTracks()
>>             {
>>                 debug() << "file: " << filename << " is orphaned" << endl;
>>                 orphanedTracks << ipodPath;
>> -                orph++;
>> +            }
>> +        }
>> +    }
>> +
>> +    return orphanedTracks;
>> +}
>> +
>> +AttributeHash
>> +IpodHandler::readTags( const QString &path, TagLib::AudioProperties::ReadStyle readStyle )
>> +{
>> +    // Tests reveal the following:
>> +    //
>> +    // TagLib::AudioProperties   Relative Time Taken
>> +    //
>> +    //  No AudioProp Reading        1
>> +    //  Fast                        1.18
>> +    //  Average                     Untested
>> +    //  Accurate                    Untested
>> +
>> +
>> +#ifdef COMPLEX_TAGLIB_FILENAME
>> +    const wchar_t * encodedName = reinterpret_cast<const wchar_t *>(path.utf16());
>> +#else
>> +    QByteArray fileName = QFile::encodeName( path );
>> +    const char * encodedName = fileName.constData(); // valid as long as fileName exists
>> +#endif
>> +
>> +    TagLib::FileRef fileref;
>> +    TagLib::Tag *tag = 0;
>> +    fileref = TagLib::FileRef( encodedName, true, readStyle );
>> +
>> +    AttributeHash attributes;
>> +    bool isValid = false;
>> +    FileType fileType = ogg;
>> +    if( !fileref.isNull() )
>> +    {
>> +        tag = fileref.tag();
>> +        if ( tag )
>> +        {
>> +            #define strip( x ) TStringToQString( x ).trimmed()
>> +
>> +            attributes["title"] = strip( tag->title() );
>> +            attributes["artist"] = strip( tag->artist() );
>> +            attributes["album"] = strip( tag->album() );
>> +            attributes["comment"] = strip( tag->comment() );
>> +            attributes["genre"] = strip( tag->genre() );
>> +            attributes["year"] = QString::number( tag->year() );
>> +            attributes["track"]  = QString::number( tag->track() );
>> +            isValid = true;
>> +        }
>> +/*
>> +        Meta::ReplayGainTagMap replayGainTags = Meta::readReplayGainTags( fileref );
>> +        if ( replayGainTags.contains( Meta::ReplayGain_Track_Gain ) )
>> +        {
>> +            attributes["trackgain"] = QString::number( replayGainTags[Meta::ReplayGain_Track_Gain] );
>> +            if ( replayGainTags.contains( Meta::ReplayGain_Track_Peak ) )
>> +                attributes["trackpeakgain"] = QString::number( replayGainTags[Meta::ReplayGain_Track_Peak] );
>> +        }
>> +        if ( replayGainTags.contains( Meta::ReplayGain_Album_Gain ) )
>> +        {
>> +            attributes["albumgain"] = QString::number( replayGainTags[Meta::ReplayGain_Album_Gain] );
>> +            if ( replayGainTags.contains( Meta::ReplayGain_Album_Peak ) )
>> +                attributes["albumpeakgain"] = QString::number( replayGainTags[Meta::ReplayGain_Album_Peak] );
>> +        }
>> +*/
>> +        QString disc;
>> +        QString compilation;
>> +
>> +        /* As mpeg implementation on TagLib uses a Tag class that's not defined on the headers,
>> +           we have to cast the files, not the tags! */
>> +        if ( TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File *>( fileref.file() ) )
>> +        {
>> +            fileType = mp3;
>> +            if ( file->ID3v2Tag() )
>> +            {
>> +                if ( !file->ID3v2Tag()->frameListMap()["TPOS"].isEmpty() )
>> +                    disc = TStringToQString( file->ID3v2Tag()->frameListMap()["TPOS"].front()->toString() ).trimmed();
>> +
>> +                if ( !file->ID3v2Tag()->frameListMap()["TBPM"].isEmpty() )
>> +                    attributes["bpm"] = TStringToQString( file->ID3v2Tag()->frameListMap()["TBPM"].front()->toString() ).trimmed().toFloat();
>> +
>> +                if ( !file->ID3v2Tag()->frameListMap()["TCOM"].isEmpty() )
>> +                    attributes["composer"] = TStringToQString( file->ID3v2Tag()->frameListMap()["TCOM"].front()->toString() ).trimmed();
>> +
>> +                if ( !file->ID3v2Tag()->frameListMap()["TPE2"].isEmpty() ) // non-standard: Apple, Microsoft
>> +                    attributes["albumArtist"] = TStringToQString( file->ID3v2Tag()->frameListMap()["TPE2"].front()->toString() ).trimmed();
>>
>> +                if ( !file->ID3v2Tag()->frameListMap()["TCMP"].isEmpty() )
>> +                    compilation = TStringToQString( file->ID3v2Tag()->frameListMap()["TCMP"].front()->toString() ).trimmed();
>> +
>> +                //FIXME: Port 2.0
>> +//                 if( images )
>> +//                     loadImagesFromTag( *file->ID3v2Tag(), *images );
>>             }
>>
>> -            if( orph > 10 )
>> -                return QStringList();
>> +            #undef strip
>> +        }
>> +
>> +        if ( TagLib::Ogg::Vorbis::File *file = dynamic_cast<TagLib::Ogg::Vorbis::File *>( fileref.file() ) )
>> +        {
>> +            fileType = ogg;
>> +            if ( file->tag() )
>> +            {
>> +                if ( !file->tag()->fieldListMap()[ "COMPOSER" ].isEmpty() )
>> +                    attributes["composer"] = TStringToQString( file->tag()->fieldListMap()["COMPOSER"].front() ).trimmed();
>> +
>> +                if ( !file->tag()->fieldListMap()[ "BPM" ].isEmpty() )
>> +                    attributes["bpm"] = TStringToQString( file->tag()->fieldListMap()["BPM"].front() ).trimmed().toFloat();
>> +
>> +                if ( !file->tag()->fieldListMap()[ "DISCNUMBER" ].isEmpty() )
>> +                    disc = TStringToQString( file->tag()->fieldListMap()["DISCNUMBER"].front() ).trimmed();
>> +
>> +                if ( !file->tag()->fieldListMap()[ "COMPILATION" ].isEmpty() )
>> +                    compilation = TStringToQString( file->tag()->fieldListMap()["COMPILATION"].front() ).trimmed();
>> +            }
>> +        }
>> +        else if ( TagLib::FLAC::File *file = dynamic_cast<TagLib::FLAC::File *>( fileref.file() ) )
>> +        {
>> +            fileType = flac;
>> +            if ( file->xiphComment() )
>> +            {
>> +                if ( !file->xiphComment()->fieldListMap()[ "COMPOSER" ].isEmpty() )
>> +                    attributes["composer"] = TStringToQString( file->xiphComment()->fieldListMap()["COMPOSER"].front() ).trimmed();
>> +
>> +                if ( !file->xiphComment()->fieldListMap()[ "BPM" ].isEmpty() )
>> +                    attributes["bpm"] = TStringToQString( file->xiphComment()->fieldListMap()["BPM"].front() ).trimmed().toFloat();
>> +
>> +                if ( !file->xiphComment()->fieldListMap()[ "DISCNUMBER" ].isEmpty() )
>> +                    disc = TStringToQString( file->xiphComment()->fieldListMap()["DISCNUMBER"].front() ).trimmed();
>> +
>> +                if ( !file->xiphComment()->fieldListMap()[ "COMPILATION" ].isEmpty() )
>> +                    compilation = TStringToQString( file->xiphComment()->fieldListMap()["COMPILATION"].front() ).trimmed();
>> +            }
>> +//             if ( images && file->ID3v2Tag() )
>> +//                 loadImagesFromTag( *file->ID3v2Tag(), *images );
>> +        }
>> +#ifdef TAGLIB_EXTRAS_FOUND
>> +        else if ( TagLib::MP4::File *file = dynamic_cast<TagLib::MP4::File *>( fileref.file() ) )
>> +        {
>> +            fileType = mp4;
>> +            TagLib::MP4::Tag *mp4tag = dynamic_cast<TagLib::MP4::Tag *>( file->tag() );
>> +            if( mp4tag )
>> +            {
>> +                if ( mp4tag->itemListMap().contains( "\xA9wrt" ) )
>> +                    attributes["composer"] = TStringToQString( mp4tag->itemListMap()["\xa9wrt"].toStringList().front() );
>> +
>> +                if ( mp4tag->itemListMap().contains( "tmpo" ) )
>> +                    attributes["bpm"] = QString::number( mp4tag->itemListMap()["tmpo"].toInt() );
>> +
>> +                if ( mp4tag->itemListMap().contains( "disk" ) )
>> +                    disc = QString::number( mp4tag->itemListMap()["disk"].toIntPair().first );
>> +
>> +                if ( mp4tag->itemListMap().contains( "cpil" ) )
>> +                    compilation = QString::number( mp4tag->itemListMap()["cpil"].toBool() ? '1' : '0' );
>> +
>> +//                 if ( images && mp4tag->cover().size() )
>> +//                     images->push_back( EmbeddedImage( mp4tag->cover(), "" ) );
>> +            }
>> +        }
>> +#endif
>> +
>> +        if ( !disc.isEmpty() )
>> +        {
>> +            int i = disc.indexOf('/');
>> +            // guard against b0rked tags
>> +            int discnumber;
>> +            if ( i != -1 )
>> +                // disc.right( i ).toInt() is total number of discs, we don't use this at the moment
>> +                discnumber = disc.left( i ).toInt();
>> +            else
>> +                discnumber = disc.toInt();
>> +            attributes["discnumber"] = QString::number( discnumber );
>> +        }
>> +
>> +        // Sometimes the file is explicitly tagged with compilation details. When it is not,
>> +        // then we need to delegate checking whether this files is in a compilation to Amarok.
>> +        if ( compilation.isEmpty() )
>> +        {
>> +            // well, it wasn't set, but if the artist is VA assume it's a compilation
>> +            //TODO: If we get pure-Qt translation support, put this back in; else functionality moved to the processor
>> +            //if ( attributes["artist"] == QObject::tr( "Various Artists" ) )
>> +            //    attributes["compilation"] = QString::number( 1 );
>> +            attributes["compilation"] = "checkforvarious";
>> +        }
>> +        else
>> +        {
>> +            int i = compilation.toInt();
>> +            attributes["compilation"] = QString::number( i );
>>         }
>>     }
>>
>> -    return orphanedTracks;
>> +    if ( !isValid )
>> +    {
>> +        std::cout << "<dud/>";
>> +        return attributes;
>> +    }
>> +
>> +    attributes["filetype"]  = QString::number( fileType );
>> +
>> +    static const int Undetermined = -2;
>> +
>> +    int bitrate = Undetermined;
>> +    int length = Undetermined;
>> +    int samplerate = Undetermined;
>> +    if( fileref.audioProperties() )
>> +    {
>> +        bitrate = fileref.audioProperties()->bitrate();
>> +        length = fileref.audioProperties()->length();
>> +        samplerate = fileref.audioProperties()->sampleRate();
>> +    }
>> +    if ( bitrate == Undetermined || length == Undetermined || samplerate == Undetermined )
>> +        attributes["audioproperties"] = "false";
>> +    else
>> +    {
>> +        attributes["audioproperties"] = "true";
>> +        attributes["bitrate"]         = QString::number( bitrate );
>> +        attributes["length"]          = QString::number( length );
>> +        attributes["samplerate"]      = QString::number( samplerate );
>> +    }
>> +
>> +    const int size = QFile( path ).size();
>> +    if( size >= 0 )
>> +        attributes["filesize"] =  QString::number( size );
>> +
>> +    return attributes;
>>  }
>>
>>  bool
>> diff --git a/src/collection/ipodcollection/handler/IpodHandler.h b/src/collection/ipodcollection/handler/IpodHandler.h
>> index ca4c53a..8ea2ca9 100644
>> --- a/src/collection/ipodcollection/handler/IpodHandler.h
>> +++ b/src/collection/ipodcollection/handler/IpodHandler.h
>> @@ -22,6 +22,10 @@
>>  #ifndef IPODHANDLER_H
>>  #define IPODHANDLER_H
>>
>> +// Taglib includes
>> +#include <audioproperties.h>
>> +#include <fileref.h>
>> +
>>  /* CMake check for GDK */
>>  #include <config-gdk.h>
>>
>> @@ -60,7 +64,7 @@ class QMutex;
>>
>>  class IpodCollection;
>>
>> -
>> +typedef QHash<QString, QString> AttributeHash;
>>  typedef QMultiMap<QString, Meta::TrackPtr> TitleMap;
>>
>>  // NOTE: podcasts NYI
>> @@ -226,6 +230,14 @@ private slots:
>>
>>  private:
>>
>> +    enum FileType
>> +    {
>> +        mp3,
>> +        ogg,
>> +        flac,
>> +        mp4
>> +    };
>> +
>>     /// Functions for ReadCapability
>>
>>     virtual void prepareToParseTracks();
>> @@ -274,6 +286,18 @@ private:
>>      */
>>     QStringList orphanedTracks();
>>
>> +    // NOTE: readTags taken from CollectionScanner.cpp, not used directly since
>> +    // CollectionScanner is now a separate utility from Amarok, and we should
>> +    // not depend on it.
>> +
>> +    /**
>> +     * Read metadata tags of a given file.
>> +     * @track Track for the file.
>> +     * @return QMap containing tags, or empty QMap on failure.
>> +     */
>> +
>> +    AttributeHash readTags( const QString &path, TagLib::AudioProperties::ReadStyle readStyle = TagLib::AudioProperties::Fast );
>> +
>>     bool removeDBTrack( Itdb_Track *track );
>>
>>     /* libgpod Information Extraction Methods */
>> @@ -315,6 +339,7 @@ private:
>>     GList            *m_currtracklist;
>>     Itdb_Track       *m_currtrack;
>>     QHash<QString,Itdb_Track*> m_files;
>> +    int m_staletracksremoved;
>>
>>     // For space checks
>>
>> @@ -400,6 +425,8 @@ private slots:
>>     void slotDBWriteSucceeded( ThreadWeaver::Job* job );
>>
>>     void slotCopyingDone( KIO::Job* job, KUrl from, KUrl to, time_t mtime, bool directory, bool renamed );
>> +
>> +    void slotOrphaned();
>>  };
>>
>>  class DBWorkerThread : public ThreadWeaver::Job
>> diff --git a/src/collection/mediadevicecollection/handler/MediaDeviceHandler.h b/src/collection/mediadevicecollection/handler/MediaDeviceHandler.h
>> index f7621a6..2dcf116 100644
>> --- a/src/collection/mediadevicecollection/handler/MediaDeviceHandler.h
>> +++ b/src/collection/mediadevicecollection/handler/MediaDeviceHandler.h
>> @@ -237,7 +237,16 @@ protected:
>>
>>     MediaDeviceHandler( QObject *parent );
>>
>> +    /** Creates a MediaDeviceTrack based on the latest track struct created as a
>> +    *  result of a copy to the device, and adds it into the collection to reflect
>> +    *  that it has been copied.
>> +    *  @param track The track to add to the collection
>> +    */
>> +
>> +    void addMediaDeviceTrackToCollection( Meta::MediaDeviceTrackPtr &track );
>> +
>>     MediaDeviceCollection   *m_memColl; /// Associated collection
>> +    ProgressBar      *m_statusbar; /// A progressbar to show progress of an operation
>>
>>     bool m_success;
>>     bool m_copyingthreadsafe; // whether or not the handler's method of copying is threadsafe
>> @@ -261,14 +270,6 @@ protected slots:
>>
>>  private:
>>
>> -    /** Creates a MediaDeviceTrack based on the latest track struct created as a
>> -    *  result of a copy to the device, and adds it into the collection to reflect
>> -    *  that it has been copied.
>> -    *  @param track The track to add to the collection
>> -    */
>> -
>> -    void addMediaDeviceTrackToCollection( Meta::MediaDeviceTrackPtr &track );
>> -
>>     /**  Removes the @param track from all the collection's maps to reflect that
>>     *  it has been removed from the collection
>>     *  @param track The track to remove from the collection
>> @@ -349,7 +350,6 @@ private:
>>     QMap<Meta::TrackPtr, QString> m_tracksFailed; /// tracks that failed to copy
>>     QHash<Meta::TrackPtr, Meta::MediaDeviceTrackPtr> m_trackSrcDst; /// points source to destTracks, for completion of addition to collection
>>
>> -    ProgressBar      *m_statusbar; /// A progressbar to show progress of an operation
>>     QMutex m_mutex; /// A make certain operations atomic when threads are at play
>>
>>     /// Capability-related variables
>>
>>
>>
>
>
>
> --
> Seb Ruiz
>
> http://www.sebruiz.net/
> http://amarok.kde.org/
>


More information about the Amarok-devel mailing list