/*************************************************************************** * Copyright (C) 2003-2005 by The Amarok Developers * * * * 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 Steet, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef AMAROK_SCANCONTROLLER_H #define AMAROK_SCANCONTROLLER_H #include #include //baseclass #include "threadmanager.h" //baseclass class CollectionDB; class KProcIO; /** * @class ScanController * @short Starts and controls the external amarokcollectionscanner application. * @author Mark Kretschmann * * The collection scanner itself is run in an external process, unlike before, where it * used to be thread. The advantage is that the scanner cannot crash the Amarok main * application any more. If it crashes we can simply restart it. * * Amarok communicates with the scanner via the ScanController class, which processes * XML entities written to stdout by the scanner process. For XML parsing an event * driven SAX2 parser is used, which can process the entities as they arrive, without * the need for a DOM document structure. */ #ifdef Q_MOC_RUN // MOC_SKIP_BEGIN class ScanController : public JobBase, public TQXmlDefaultHandler // MOC_SKIP_END #else // Q_MOC_RUN class ScanController : public ThreadManager::DependentJob, public TQXmlDefaultHandler #endif // Q_MOC_RUN { Q_OBJECT public: static const int RestartEventType = 8891; class RestartEvent : public TQCustomEvent { public: RestartEvent() : TQCustomEvent( RestartEventType ) {} }; static const int PlaylistFoundEventType = 8890; class PlaylistFoundEvent : public TQCustomEvent { public: PlaylistFoundEvent( TQString path ) : TQCustomEvent( PlaylistFoundEventType ) , m_path( path ) {} TQString path() { return m_path; } private: TQString m_path; }; public: ScanController( CollectionDB* parent, bool incremental, const TQStringList& folders = TQStringList() ); ~ScanController(); static ScanController* instance(); virtual void completeJob( void ); bool isIncremental() const { return m_incremental; } bool hasChanged() const { return m_hasChanged; } void notifyThisBundle( MetaBundle* bundle ); bool isPaused() { return m_isPaused; } bool tablesCreated() { return m_tablesCreated; } signals: void scannerAcknowledged(); void scanDone( bool changed ); public slots: bool requestPause(); bool requestUnpause(); void requestAcknowledged(); void slotFileMoved( const TQString &src, const TQString &dest ); private slots: void slotReadReady(); private: void initIncremental(); virtual bool doJob(); static void setInstance( ScanController* instance ); bool startElement( const TQString&, const TQString &localName, const TQString&, const TQXmlAttributes &attrs ); void customEvent( TQCustomEvent* ); // Member variables: static const uint MAX_RESTARTS = 80; static const uint MAX_FAILURE_PERCENTAGE = 5; KProcIO* m_scanner; TQStringList m_folders; TQStringList m_foldersToRemove; bool m_incremental; bool m_hasChanged; TQString m_xmlData; TQMutex m_dataMutex; TQXmlInputSource* m_source; TQXmlSimpleReader* m_reader; TQStringList m_crashedFiles; // Every file that the collection scanner finds is marked // here, as well as the source of all files that the AFT code // detects as having been moved. These are the files that // have definitely not been deleted. The key is the absolute // path. TQMap m_filesAdded; TQMap m_filesDeleted; TQMutex m_fileMapsMutex; static ScanController* currController; MetaBundle* m_waitingBundle; bool m_lastCommandPaused; bool m_isPaused; bool m_tablesCreated; int m_scanCount; }; #endif // AMAROK_SCANCONTROLLER_H