File indexing completed on 2024-05-05 04:48:50
0001 /**************************************************************************************** 0002 * Copyright (c) 2003-2008 Mark Kretschmann <kretschmann@kde.org> * 0003 * Copyright (c) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com> * 0004 * Copyright (c) 2007 Casey Link <unnamedrambler@gmail.com> * 0005 * Copyright (c) 2008-2009 Jeff Mitchell <mitchell@kde.org> * 0006 * Copyright (c) 2010-2011 Ralf Engels <ralf-engels@gmx.de> * 0007 * Copyright (c) 2011 Bart Cerneels <bart.cerneels@kde.org> * 0008 * Copyright (c) 2013 Ralf Engels <ralf-engels@gmx.de> * 0009 * * 0010 * This program is free software; you can redistribute it and/or modify it under * 0011 * the terms of the GNU General Public License as published by the Free Software * 0012 * Foundation; either version 2 of the License, or (at your option) any later * 0013 * version. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0016 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0017 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0018 * * 0019 * You should have received a copy of the GNU General Public License along with * 0020 * this program. If not, see <http://www.gnu.org/licenses/>. * 0021 ****************************************************************************************/ 0022 0023 #ifndef GENERIC_SCANNERJOB_H 0024 #define GENERIC_SCANNERJOB_H 0025 0026 #include "GenericScanManager.h" 0027 #include "collectionscanner/Directory.h" 0028 0029 #include <ThreadWeaver/Job> 0030 #include <QUrl> 0031 0032 #include <QObject> 0033 #include <QString> 0034 #include <QMutex> 0035 #include <QWaitCondition> 0036 #include <QXmlStreamReader> 0037 #include <KLocalizedString> 0038 namespace CollectionScanner { 0039 class Directory; 0040 } 0041 class KProcess; 0042 class QSharedMemory; 0043 template<class T> 0044 class QSharedPointer; 0045 0046 /** This is the job that does all the hard work with scanning. 0047 It will receive new data from the scanner process, parse it and call the 0048 ScanResultProcessor. 0049 0050 The job will delete itself when finished or aborted. (This is important 0051 as a separate process should not be killed by another process out of order) 0052 0053 Design Decision: The ScannerJob should parse the xml from the amarok collection 0054 scanner while it's being produced. In case the collection scanner crashes 0055 the scanner process will be restarted and the xml output from the scanner 0056 seamlessly appended. 0057 */ 0058 class GenericScannerJob : public QObject, public ThreadWeaver::Job 0059 { 0060 Q_OBJECT 0061 0062 public: 0063 /** Creates the parse job. 0064 The constructor itself should be called from the UI thread. 0065 @param manager The scan manager. 0066 @param input An input io device for the scanner. The input must remain valid as long as the scanner is working (TODO: is this smart?) 0067 @param type The scan type. @see GenericScanManager::ScanType 0068 */ 0069 GenericScannerJob( GenericScanManager* manager, 0070 QIODevice *input, 0071 GenericScanManager::ScanType type ); 0072 0073 GenericScannerJob( GenericScanManager* manager, 0074 const QStringList &scanDirsRequested, 0075 GenericScanManager::ScanType type, 0076 bool recursive = true, 0077 bool detectCharset = false ); 0078 0079 ~GenericScannerJob() override; 0080 0081 /* ThreadWeaver::Job virtual methods */ 0082 void run(ThreadWeaver::JobPointer self = QSharedPointer<ThreadWeaver::Job>(), ThreadWeaver::Thread *thread = nullptr) override; 0083 virtual void abort(); 0084 void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; 0085 void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; 0086 0087 Q_SIGNALS: 0088 void started( GenericScanManager::ScanType type ); 0089 0090 /** Gives the estimated count of directories that this scan will have. 0091 * This signal might not be emitted or emitted multiple times if the 0092 * count is updated. 0093 */ 0094 void directoryCount( int count ); 0095 0096 /** 0097 * Emitted once we get the complete data for a directory. 0098 * 0099 * @param dir The directory structure with all containing tracks. It is 0100 * memory-managed using QSharedPointer - you are not allowed to convert it to a 0101 * plain pointer unless you can guarantee another QSharedPointer instance pointing 0102 * to the same object exist for the time of the existence of the plain pointer. 0103 */ 0104 void directoryScanned( QSharedPointer<CollectionScanner::Directory> dir ); 0105 0106 void succeeded(); 0107 void failed( QString message ); 0108 // and the ThreadWeaver::Job also emits done 0109 0110 /** This signal is emitted when this job is being processed by a thread. */ 0111 void started(ThreadWeaver::JobPointer); 0112 /** This signal is emitted when the job has been finished (no matter if it succeeded or not). */ 0113 void done(ThreadWeaver::JobPointer); 0114 /** This job has failed. 0115 * This signal is emitted when success() returns false after the job is executed. */ 0116 void failed(ThreadWeaver::JobPointer); 0117 0118 private: 0119 /** Returns the path to the collection scanner */ 0120 QString scannerPath(); 0121 0122 /** Tries to create the scanner process. 0123 * If unable to create the scanner a failed signal will 0124 * be emitted by this method. 0125 * @returns true if it managed to start. 0126 */ 0127 bool createScannerProcess( bool restart = false ); 0128 0129 /** Tries to restart the scanner process. 0130 * If unable to restart the scanner a failed signal will 0131 * be emitted by this method. 0132 * @returns true if it managed to restart. 0133 */ 0134 bool restartScannerProcess(); 0135 0136 void closeScannerProcess(); 0137 0138 /** Parses the currently available input from m_reader. 0139 * @returns true if parsing the file is finished successfully. 0140 */ 0141 bool parseScannerOutput(); 0142 0143 /** Wait for the scanner to produce some output or die */ 0144 void getScannerOutput(); 0145 0146 GenericScanManager* m_manager; 0147 GenericScanManager::ScanType m_type; 0148 QStringList m_scanDirsRequested; 0149 QIODevice *m_input; 0150 0151 int m_restartCount; 0152 bool m_abortRequested; 0153 QString m_incompleteTagBuffer; // strings received via addNewXmlData but not terminated by either a </directory> or a </scanner> 0154 0155 KProcess *m_scanner; 0156 QString m_batchfilePath; 0157 QSharedMemory *m_scannerStateMemory; // a persistent storage of the current scanner state in case it needs to be restarted. 0158 bool m_recursive; 0159 bool m_charsetDetect; 0160 0161 QXmlStreamReader m_reader; 0162 0163 QMutex m_mutex; // only protects m_abortRequested and the abort reason 0164 }; 0165 0166 #endif // SCANNERJOB_H