/*************************************************************************** * Copyright (C) 2003-2005 Max Howell * * (C) 2003-2010 Mark Kretschmann * * (C) 2005-2007 Alexandre Oliveira * * (C) 2008 Dan Meltzer * * (C) 2008-2009 Jeff Mitchell * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "Directory.h" #include "collectionscanner/ScanningState.h" #include "collectionscanner/Track.h" #include "collectionscanner/utils.h" #include #include #include #include #include #include #include #include #include #include CollectionScanner::Directory::Directory( const QString &path, CollectionScanner::ScanningState *state, bool skip ) : m_ignored( false ) { m_path = path; m_rpath = QDir::current().relativeFilePath( path ); m_mtime = QFileInfo( path ).lastModified().toTime_t(); m_skipped = skip; if( m_skipped ) return; QDir dir( path ); if( dir.exists( "fmps_ignore" ) ) { m_ignored = true; return; } QStringList validImages; validImages << "jpg" << "png" << "gif" << "jpeg" << "bmp" << "svg" << "xpm"; QStringList validPlaylists; validPlaylists << "m3u" << "pls" << "xspf"; // --- check if we were restarted and failed at a file QStringList badFiles; if( state->lastDirectory() == path ) { badFiles << state->badFiles(); QString lastFile = state->lastFile(); if( !lastFile.isEmpty() ) { badFiles << state->lastFile(); state->setBadFiles( badFiles ); } } else state->setLastDirectory( path ); state->setLastFile( QString() ); // reset so we don't add a leftover file dir.setFilter( QDir::NoDotAndDotDot | QDir::Files ); QFileInfoList fileInfos = dir.entryInfoList(); foreach( const QFileInfo &fi, fileInfos ) { if( !fi.exists() ) continue; const QFileInfo &f = fi.isSymLink() ? QFileInfo( fi.symLinkTarget() ) : fi; if( badFiles.contains( f.absoluteFilePath() ) ) continue; const QString suffix = fi.suffix().toLower(); const QString filePath = f.absoluteFilePath(); // -- cover image ? if( validImages.contains( suffix ) ) m_covers.append( filePath ); // -- playlist ? else if( validPlaylists.contains( suffix ) ) m_playlists.append( CollectionScanner::Playlist( filePath ) ); // -- audio track ? else { // remember the last file before it get's dangerous. Before starting taglib state->setLastFile( f.absoluteFilePath() ); CollectionScanner::Track *newTrack = new CollectionScanner::Track( filePath, this ); if( newTrack->isValid() ) m_tracks.append( newTrack ); else delete newTrack; } } } CollectionScanner::Directory::Directory( QXmlStreamReader *reader ) : m_mtime( 0 ) , m_skipped( false ) , m_ignored( false ) { // improve scanner with skipCurrentElement as soon as Amarok requires Qt 4.6 while (!reader->atEnd()) { reader->readNext(); if( reader->isStartElement() ) { QStringRef name = reader->name(); if( name == "path" ) m_path = reader->readElementText(QXmlStreamReader::SkipChildElements); else if( name == "rpath" ) m_rpath = reader->readElementText(QXmlStreamReader::SkipChildElements); else if( name == "mtime" ) m_mtime = reader->readElementText(QXmlStreamReader::SkipChildElements).toUInt(); else if( name == "cover" ) m_covers.append(reader->readElementText(QXmlStreamReader::SkipChildElements)); else if( name == "skipped" ) { m_skipped = true; reader->skipCurrentElement(); } else if( name == "ignored" ) { m_ignored = true; reader->skipCurrentElement(); } else if( name == "track" ) m_tracks.append( new CollectionScanner::Track( reader, this ) ); else if( name == "playlist" ) m_playlists.append( CollectionScanner::Playlist( reader ) ); else { qDebug() << "Unexpected xml start element"<skipCurrentElement(); } } else if( reader->isEndElement() ) { break; } } } CollectionScanner::Directory::~Directory() { foreach( CollectionScanner::Track *track, m_tracks ) delete track; } QString CollectionScanner::Directory::path() const { return m_path; } QString CollectionScanner::Directory::rpath() const { return m_rpath; } uint CollectionScanner::Directory::mtime() const { return m_mtime; } bool CollectionScanner::Directory::isSkipped() const { return m_skipped; } const QStringList& CollectionScanner::Directory::covers() const { return m_covers; } const QList& CollectionScanner::Directory::tracks() const { return m_tracks; } const QList& CollectionScanner::Directory::playlists() const { return m_playlists; } void CollectionScanner::Directory::toXml( QXmlStreamWriter *writer ) const { writer->writeTextElement( "path", escapeXml10(m_path) ); writer->writeTextElement( "rpath", escapeXml10(m_rpath) ); writer->writeTextElement( "mtime", QString::number( m_mtime ) ); if( m_skipped ) writer->writeEmptyElement( "skipped" ); if( m_ignored ) writer->writeEmptyElement( "ignored" ); foreach( const QString &cover, m_covers ) { writer->writeTextElement( "cover", escapeXml10(cover) ); } foreach( CollectionScanner::Track *track, m_tracks ) { writer->writeStartElement( QLatin1String("track") ); track->toXml( writer ); writer->writeEndElement(); } foreach( const CollectionScanner::Playlist &playlist, m_playlists ) { writer->writeStartElement( "playlist" ); playlist.toXml( writer ); writer->writeEndElement(); } }