/*************************************************************************** * Copyright (C) 2006-2017 by Ilya Kotov * * forkotov02@ya.ru * * * * 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 #include #include #include #include #include "fileloader_p.h" #include "qmmpuisettings.h" #include "playlistitem.h" #include "playlistparser.h" #include "playlisttrack.h" FileLoader::FileLoader(QObject *parent) : QThread(parent) { qRegisterMetaType >("QList"); m_settings = QmmpUiSettings::instance(); m_finished = false; m_use_meta = false; connect(qApp, SIGNAL(aboutToQuit()), SLOT(finish())); } FileLoader::~FileLoader() {} QList FileLoader::processFile(const QString &path, QStringList *ignoredPaths) { QList tracks; QList infoList = MetaDataManager::instance()->createPlayList(path, m_use_meta, ignoredPaths); foreach (FileInfo *info, infoList) { tracks.append(new PlayListTrack(info)); } qDeleteAll(infoList); return tracks; } void FileLoader::insertPlayList(const QString &fmt, const QByteArray &contents, PlayListItem *before) { QList tracks = PlayListParser::loadPlaylist(fmt, contents); while (!tracks.isEmpty() && !m_finished) { PlayListTrack *t = tracks.takeFirst(); QList infoList = MetaDataManager::instance()->createPlayList(t->url(), m_use_meta); if(infoList.count() != 1) //invalid or unsupported track { qDeleteAll(infoList); infoList.clear(); delete t; continue; } FileInfo *info = infoList.first(); if(!info->metaData(Qmmp::ALBUM).isEmpty() && !info->metaData(Qmmp::ARTIST).isEmpty()) t->updateMetaData(infoList.first()); emit newTracksToInsert(before, QList() << t); delete info; } //clear remaining tracks qDeleteAll(tracks); tracks.clear(); } void FileLoader::insertPlayList(const QString &path, PlayListItem *before) { QList tracks = PlayListParser::loadPlaylist(path); while (!tracks.isEmpty() && !m_finished) { PlayListTrack *t = tracks.takeFirst(); QList infoList = MetaDataManager::instance()->createPlayList(t->url(), m_use_meta); if(infoList.count() != 1) //invalid or unsupported track { qDeleteAll(infoList); infoList.clear(); delete t; continue; } FileInfo *info = infoList.first(); if(!info->metaData(Qmmp::ALBUM).isEmpty() && !info->metaData(Qmmp::ARTIST).isEmpty()) t->updateMetaData(infoList.first()); emit newTracksToInsert(before, QList() << t); delete info; } //clear remaining tracks qDeleteAll(tracks); tracks.clear(); } void FileLoader::addDirectory(const QString& s, PlayListItem *before) { QList tracks; QStringList ignoredPaths; QDir dir(s); dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); dir.setSorting(QDir::Name); QFileInfoList l = dir.entryInfoList(m_filters); foreach(QFileInfo info, l) { if(checkRestrictFilters(info) && checkExcludeFilters(info)) { QStringList paths; tracks.append(processFile(info.absoluteFilePath (), &ignoredPaths)); ignoredPaths.append(paths); } if (m_finished) { qDeleteAll(tracks); tracks.clear(); return; } if(tracks.count() > 30) //do not send more than 30 tracks at once { removeIgnoredTracks(&tracks, ignoredPaths); emit newTracksToInsert(before, tracks); tracks.clear(); ignoredPaths.clear(); } } if(!tracks.isEmpty()) { removeIgnoredTracks(&tracks, ignoredPaths); emit newTracksToInsert(before, tracks); ignoredPaths.clear(); } dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); dir.setSorting(QDir::Name); l.clear(); l = dir.entryInfoList(); for (int i = 0; i < l.size(); ++i) { QFileInfo fileInfo = l.at(i); addDirectory(fileInfo.absoluteFilePath (), before); if (m_finished) return; } } void FileLoader::run() { m_finished = false; m_mutex.lock(); if(m_tasks.isEmpty()) { m_mutex.unlock(); return; } m_mutex.unlock(); while(!m_finished) { m_mutex.lock(); LoaderTask i = m_tasks.dequeue(); m_mutex.unlock(); PlayListItem *before = i.before; QString path = i.path; if(!path.isEmpty()) { QFileInfo info(path); if(info.isDir()) { addDirectory(path, before); } else if(info.isFile() && PlayListParser::isPlayList(path)) { insertPlayList(path, before); } else if(info.isFile() || path.contains("://")) { QList tracks = processFile(path); if(!tracks.isEmpty()) { emit newTracksToInsert(before, tracks); } } } else if(!i.playListContent.isEmpty() && !i.playListFormat.isEmpty()) { insertPlayList(i.playListFormat, i.playListContent, before); } m_mutex.lock(); if(m_tasks.isEmpty()) { m_mutex.unlock(); break; } m_mutex.unlock(); } } void FileLoader::add(const QString &path) { insert(0, QStringList() << path); } void FileLoader::add(const QStringList &paths) { insert(0, paths); } void FileLoader::addPlayList(const QString &fmt, const QByteArray &data) { m_mutex.lock(); LoaderTask task; task.before = 0; task.playListFormat = fmt; task.playListContent = data; m_tasks.append(task); m_mutex.unlock(); if(!isRunning()) { MetaDataManager::instance()->prepareForAnotherThread(); PlayListParser::loadFormats(); m_filters = MetaDataManager::instance()->nameFilters(); m_use_meta = m_settings->useMetadata(); } start(QThread::IdlePriority); } void FileLoader::insert(PlayListItem *before, const QString &path) { insert(before, QStringList() << path); } void FileLoader::insert(PlayListItem *before, const QStringList &paths) { m_mutex.lock(); foreach (QString path, paths) { LoaderTask task; task.before = before; task.path = QDir::fromNativeSeparators(path); m_tasks.append(task); } m_mutex.unlock(); if(!isRunning()) { MetaDataManager::instance()->prepareForAnotherThread(); m_filters = MetaDataManager::instance()->nameFilters(); m_use_meta = m_settings->useMetadata(); } start(QThread::IdlePriority); } void FileLoader::finish() { m_finished = true; wait(); m_tasks.clear(); } bool FileLoader::checkRestrictFilters(const QFileInfo &info) { if(m_settings->restrictFilters().isEmpty()) return true; foreach(QString filter, m_settings->restrictFilters()) { QRegExp regexp (filter, Qt::CaseInsensitive, QRegExp::Wildcard); if(regexp.exactMatch(info.absoluteFilePath())) return true; } return false; } bool FileLoader::checkExcludeFilters(const QFileInfo &info) { if(m_settings->excludeFilters().isEmpty()) return true; foreach(QString filter, m_settings->excludeFilters()) { QRegExp regexp (filter, Qt::CaseInsensitive, QRegExp::Wildcard); if(regexp.exactMatch(info.absoluteFilePath())) return false; } return true; } void FileLoader::removeIgnoredTracks(QList *tracks, const QStringList &ignoredPaths) { if(ignoredPaths.isEmpty()) return; foreach(PlayListTrack *track, *tracks) { if(ignoredPaths.contains(track->url())) { tracks->removeAll(track); delete track; } } }