diff options
-rw-r--r-- | config.tests/taglib/main.cpp | 47 | ||||
-rw-r--r-- | config.tests/taglib/taglib.pro | 12 | ||||
-rw-r--r-- | qtivi.pro | 1 | ||||
-rw-r--r-- | src/plugins/ivimedia/media_simulator/media_simulator.json | 2 | ||||
-rw-r--r-- | src/plugins/ivimedia/media_simulator/media_simulator.pro | 15 | ||||
-rw-r--r-- | src/plugins/ivimedia/media_simulator/mediadiscoverybackend.cpp | 2 | ||||
-rw-r--r-- | src/plugins/ivimedia/media_simulator/mediadiscoverybackend.h | 4 | ||||
-rw-r--r-- | src/plugins/ivimedia/media_simulator/mediaindexerbackend.cpp | 224 | ||||
-rw-r--r-- | src/plugins/ivimedia/media_simulator/mediaindexerbackend.h | 87 | ||||
-rw-r--r-- | src/plugins/ivimedia/media_simulator/mediaplugin.cpp | 10 | ||||
-rw-r--r-- | src/plugins/ivimedia/media_simulator/mediaplugin.h | 2 |
11 files changed, 403 insertions, 3 deletions
diff --git a/config.tests/taglib/main.cpp b/config.tests/taglib/main.cpp new file mode 100644 index 0000000..1f14eae --- /dev/null +++ b/config.tests/taglib/main.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtIvi module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +#include <taglib.h> + +int main() +{ + return 0; +} diff --git a/config.tests/taglib/taglib.pro b/config.tests/taglib/taglib.pro new file mode 100644 index 0000000..563372f --- /dev/null +++ b/config.tests/taglib/taglib.pro @@ -0,0 +1,12 @@ +TARGET = taglib +QT = core + +!contains(QT_CONFIG, no-pkg-config) { + CONFIG += link_pkgconfig + PKGCONFIG += taglib +} else { + LIBS += -ltag +} + +# Input +SOURCES += main.cpp @@ -13,6 +13,7 @@ QML_IMPORT_PATH = $$shadowed($$PWD)/qml lessThan(QT_MAJOR_VERSION, 5): error("QtIvi only supports Qt 5.") load(configure) qtCompileTest(dlt) +qtCompileTest(taglib) load(qt_parts) OTHER_FILES += sync.profile diff --git a/src/plugins/ivimedia/media_simulator/media_simulator.json b/src/plugins/ivimedia/media_simulator/media_simulator.json index 74b66c2..5e15d21 100644 --- a/src/plugins/ivimedia/media_simulator/media_simulator.json +++ b/src/plugins/ivimedia/media_simulator/media_simulator.json @@ -1,3 +1,3 @@ { - "interfaces" : [ "com.qt-project.qtivi.MediaPlayer", "com.qt-project.qtivi.SearchAndBrowseModel", "com.qt-project.qtivi.MediaDiscovery" ] + "interfaces" : [ "com.qt-project.qtivi.MediaPlayer", "com.qt-project.qtivi.SearchAndBrowseModel", "com.qt-project.qtivi.MediaDiscovery", "com.qt-project.qtivi.MediaIndexer"] } diff --git a/src/plugins/ivimedia/media_simulator/media_simulator.pro b/src/plugins/ivimedia/media_simulator/media_simulator.pro index 423fffe..fca52ad 100644 --- a/src/plugins/ivimedia/media_simulator/media_simulator.pro +++ b/src/plugins/ivimedia/media_simulator/media_simulator.pro @@ -8,6 +8,15 @@ QT += core ivicore ivimedia sql multimedia load(qt_plugin) +config_taglib { + DEFINES += QT_TAGLIB + !contains(QT_CONFIG, no-pkg-config) { + CONFIG += link_pkgconfig + PKGCONFIG = taglib + } else { + LIBS += -ltag + } +} DISTFILES += media_simulator.json @@ -17,7 +26,8 @@ HEADERS += \ searchandbrowsebackend.h \ mediadiscoverybackend.h \ usbdevice.h \ - usbbrowsebackend.h + usbbrowsebackend.h \ + mediaindexerbackend.h SOURCES += \ mediaplugin.cpp \ @@ -25,4 +35,5 @@ SOURCES += \ searchandbrowsebackend.cpp \ mediadiscoverybackend.cpp \ usbdevice.cpp \ - usbbrowsebackend.cpp + usbbrowsebackend.cpp \ + mediaindexerbackend.cpp diff --git a/src/plugins/ivimedia/media_simulator/mediadiscoverybackend.cpp b/src/plugins/ivimedia/media_simulator/mediadiscoverybackend.cpp index fabb4c9..55e5b1f 100644 --- a/src/plugins/ivimedia/media_simulator/mediadiscoverybackend.cpp +++ b/src/plugins/ivimedia/media_simulator/mediadiscoverybackend.cpp @@ -83,6 +83,7 @@ void MediaDiscoveryBackend::onDirectoryChanged(const QString &path) qDebug() << "Removing USB Device for: " << folder; QIviServiceObject *device = m_deviceMap.take(folder); emit deviceRemoved(device); + emit mediaDirectoryRemoved(deviceFolder.absoluteFilePath(folder)); } } @@ -95,5 +96,6 @@ void MediaDiscoveryBackend::onDirectoryChanged(const QString &path) USBDevice *device = new USBDevice(deviceFolder.absoluteFilePath(folder)); m_deviceMap.insert(folder, device); emit deviceAdded(device); + emit mediaDirectoryAdded(deviceFolder.absoluteFilePath(folder)); } } diff --git a/src/plugins/ivimedia/media_simulator/mediadiscoverybackend.h b/src/plugins/ivimedia/media_simulator/mediadiscoverybackend.h index 9a10f91..4864993 100644 --- a/src/plugins/ivimedia/media_simulator/mediadiscoverybackend.h +++ b/src/plugins/ivimedia/media_simulator/mediadiscoverybackend.h @@ -58,6 +58,10 @@ public: private slots: void onDirectoryChanged(const QString &path); +signals: + void mediaDirectoryAdded(const QString& path); + void mediaDirectoryRemoved(const QString& path); + private: QString m_deviceFolder; #ifndef QT_NO_FILESYSTEMWATCHER diff --git a/src/plugins/ivimedia/media_simulator/mediaindexerbackend.cpp b/src/plugins/ivimedia/media_simulator/mediaindexerbackend.cpp new file mode 100644 index 0000000..e73e1a4 --- /dev/null +++ b/src/plugins/ivimedia/media_simulator/mediaindexerbackend.cpp @@ -0,0 +1,224 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtIvi module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +#include "mediaindexerbackend.h" +#include <QtDebug> +#include <QSqlQuery> +#include <QSqlError> +#include <QDirIterator> +#include <QtConcurrent/QtConcurrent> + +#ifdef QT_TAGLIB +#include <taglib.h> +#include <tag.h> +#include <tstring.h> +#include <fileref.h> +#endif + +MediaIndexerBackend::MediaIndexerBackend(const QSqlDatabase &database, QObject *parent) + : QIviMediaIndexerControlBackendInterface(parent) + , m_db(database) +{ + connect(&m_watcher, SIGNAL(finished()), this, SLOT(onScanFinished())); + + QString mediaFolder = QDir::homePath() + QLatin1String("/media"); + const QByteArray customMediaFolder = qgetenv("QTIVIMEDIA_SIMULATOR_LOCALMEDIAFOLDER"); + if (customMediaFolder.isEmpty()) + qCritical() << "QTIVIMEDIA_SIMULATOR_LOCALMEDIAFOLDER environment variable is not set, falling back to:" << mediaFolder; + else + mediaFolder = customMediaFolder; + +#ifndef QT_TAGLIB + qWarning() << "The indexer simulation doesn't work correctly without an installed taglib"; +#endif + + //We want to have the indexer running also when the Indexing interface is not used. + addMediaFolder(mediaFolder); +} + +void MediaIndexerBackend::initialize() +{ +} + +void MediaIndexerBackend::pause() +{ + qWarning("SIMULATION: Pausing the indexing is not supported"); +} + +void MediaIndexerBackend::resume() +{ + qWarning("SIMULATION: Resuming the indexing is not supported"); +} + +void MediaIndexerBackend::addMediaFolder(const QString &path) +{ + ScanData data; + data.remove = false; + data.folder = path; + m_folderQueue.append(data); + + scanNext(); +} + +void MediaIndexerBackend::removeMediaFolder(const QString &path) +{ + ScanData data; + data.remove = true; + data.folder = path; + m_folderQueue.append(data); + + scanNext(); +} + +bool MediaIndexerBackend::scanWorker(const QString &mediaDir, bool removeData) +{ + emit stateChanged(QIviMediaIndexerControl::Active); + + if (removeData) { + qWarning() << "Removing content: " << mediaDir; + QSqlQuery query(m_db); + + bool ret = query.exec(QString("DELETE from track WHERE file LIKE '%1%'").arg(mediaDir)); + + if (!ret) { + emit stateChanged(QIviMediaIndexerControl::Error); + qWarning() << "remove query:" << query.lastError().text(); + return false; + } + + return true; + } + + qWarning() << "Scanning path: " << mediaDir; + + QSqlQuery query(m_db); + + bool ret = query.exec("CREATE TABLE IF NOT EXISTS track " + "(id integer primary key, " + "trackName varchar(200), " + "albumName varchar(200), " + "artistName varchar(200), " + "genre varchar(200), " + "number integer," + "file varchar(200)," + "UNIQUE(file))"); + + if (!ret) { + emit stateChanged(QIviMediaIndexerControl::Error); + qWarning() << "create query:" << query.lastError().text(); + return false; + } + + QStringList mediaFiles; + mediaFiles << "*.mp3"; + + QVector<QString> files; + QDirIterator it(mediaDir, mediaFiles, QDir::Files, QDirIterator::Subdirectories); + qWarning() << "Calculating total file count"; + + int totalFileCount = 0; + while (it.hasNext()) { + files.append(it.next()); + totalFileCount++; + } + qWarning() << "total files: " << totalFileCount; + int currentFileIndex = 0; + for (const QString &fileName : files) { + qWarning() << "Processing file:" << fileName; + +#ifdef QT_TAGLIB + TagLib::FileRef f(fileName.toLocal8Bit()); + + QSqlQuery query(m_db); + + query.prepare("INSERT OR IGNORE INTO track (trackName, albumName, artistName, genre, number, file) " + "VALUES (:trackName, :albumName, :artistName, :genre, :number, :file)"); + + query.bindValue(":trackName", QLatin1String(f.tag()->title().toCString())); + query.bindValue(":albumName", QLatin1String(f.tag()->album().toCString())); + query.bindValue(":artistName", QLatin1String(f.tag()->artist().toCString())); + query.bindValue(":genre", QLatin1String(f.tag()->genre().toCString())); + query.bindValue(":number", f.tag()->track()); + query.bindValue(":file", fileName); + + bool ret = query.exec(); + + if (!ret) { + emit stateChanged(QIviMediaIndexerControl::Error); + qWarning() << "insert query:" << query.lastQuery() << query.lastError().text(); + return false; + } else { + emit progressChanged(currentFileIndex/totalFileCount); + } +#else + emit progressChanged(currentFileIndex/totalFileCount); +#endif + currentFileIndex++; + + } + + return true; +} + +void MediaIndexerBackend::onScanFinished() +{ + if (!m_folderQueue.isEmpty()) { + scanNext(); + return; + } + + qDebug() << "Scanning done"; + emit indexingDone(); + + //If the last run didn't succeed we will stay in the Error state + if (m_watcher.future().result()) + emit stateChanged(QIviMediaIndexerControl::Idle); +} + +void MediaIndexerBackend::scanNext() +{ + if (m_watcher.isRunning()) + return; + + ScanData data = m_folderQueue.dequeue(); + m_currentFolder = data.folder; + m_watcher.setFuture(QtConcurrent::run(this, &MediaIndexerBackend::scanWorker, m_currentFolder, data.remove)); +} diff --git a/src/plugins/ivimedia/media_simulator/mediaindexerbackend.h b/src/plugins/ivimedia/media_simulator/mediaindexerbackend.h new file mode 100644 index 0000000..1d3ee2f --- /dev/null +++ b/src/plugins/ivimedia/media_simulator/mediaindexerbackend.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtIvi module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +#ifndef MEDIAINDEXERBACKEND_H +#define MEDIAINDEXERBACKEND_H + +#include <QtIviMedia/QIviMediaIndexerControlBackendInterface> +#include <QtIviMedia/QIviMediaIndexerControl> + +#include <QSqlDatabase> +#include <QQueue> +#include <QFutureWatcher> + +class MediaIndexerBackend : public QIviMediaIndexerControlBackendInterface +{ + Q_OBJECT +public: + explicit MediaIndexerBackend(const QSqlDatabase &database, QObject *parent = 0); + + virtual void initialize() Q_DECL_OVERRIDE; + virtual void pause() Q_DECL_OVERRIDE; + virtual void resume() Q_DECL_OVERRIDE; + +signals: + void indexingDone(); + +public slots: + void addMediaFolder(const QString &path); + void removeMediaFolder(const QString &path); + +private slots: + bool scanWorker(const QString &mediaDir, bool removeData); + void onScanFinished(); + +private: + void scanNext(); + + QSqlDatabase m_db; + struct ScanData { + bool remove; + QString folder; + }; + + QQueue<ScanData> m_folderQueue; + QString m_currentFolder; + QFutureWatcher<bool> m_watcher; +}; + +#endif // MEDIAINDEXERBACKEND_H diff --git a/src/plugins/ivimedia/media_simulator/mediaplugin.cpp b/src/plugins/ivimedia/media_simulator/mediaplugin.cpp index f7840ed..1d01723 100644 --- a/src/plugins/ivimedia/media_simulator/mediaplugin.cpp +++ b/src/plugins/ivimedia/media_simulator/mediaplugin.cpp @@ -44,6 +44,7 @@ #include "mediaplayerbackend.h" #include "searchandbrowsebackend.h" #include "mediadiscoverybackend.h" +#include "mediaindexerbackend.h" #include <QtIviMedia/QIviMediaPlayer> #include <QtIviCore/QIviSearchAndBrowseModel> @@ -63,6 +64,12 @@ MediaPlugin::MediaPlugin(QObject *parent) m_player = new MediaPlayerBackend(m_db, this); m_browse = new SearchAndBrowseBackend(m_db, this); + m_indexer = new MediaIndexerBackend(m_db, this); + + connect(m_discovery, &MediaDiscoveryBackend::mediaDirectoryAdded, + m_indexer, &MediaIndexerBackend::addMediaFolder); + connect(m_discovery, &MediaDiscoveryBackend::mediaDirectoryRemoved, + m_indexer, &MediaIndexerBackend::removeMediaFolder); } QStringList MediaPlugin::interfaces() const @@ -71,6 +78,7 @@ QStringList MediaPlugin::interfaces() const list << QIviStringMediaPlayerInterfaceName; list << QIviStringSearchAndBrowseModelInterfaceName; list << QIviStringMediaDeviceDiscoveryInterfaceName; + list << QIviStringMediaIndexerInterfaceName; return list; } @@ -82,6 +90,8 @@ QObject *MediaPlugin::interfaceInstance(const QString &interface) const return m_browse; else if (interface == QIviStringMediaDeviceDiscoveryInterfaceName) return m_discovery; + else if (interface == QIviStringMediaIndexerInterfaceName) + return m_indexer; return 0; } diff --git a/src/plugins/ivimedia/media_simulator/mediaplugin.h b/src/plugins/ivimedia/media_simulator/mediaplugin.h index 7e010ca..a391277 100644 --- a/src/plugins/ivimedia/media_simulator/mediaplugin.h +++ b/src/plugins/ivimedia/media_simulator/mediaplugin.h @@ -49,6 +49,7 @@ class MediaPlayerBackend; class SearchAndBrowseBackend; class MediaDiscoveryBackend; +class MediaIndexerBackend; class MediaPlugin : public QObject, QIviServiceInterface { @@ -66,6 +67,7 @@ private: MediaPlayerBackend *m_player; SearchAndBrowseBackend *m_browse; MediaDiscoveryBackend *m_discovery; + MediaIndexerBackend *m_indexer; QSqlDatabase m_db; }; |