[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