summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.tests/taglib/main.cpp47
-rw-r--r--config.tests/taglib/taglib.pro12
-rw-r--r--qtivi.pro1
-rw-r--r--src/plugins/ivimedia/media_simulator/media_simulator.json2
-rw-r--r--src/plugins/ivimedia/media_simulator/media_simulator.pro15
-rw-r--r--src/plugins/ivimedia/media_simulator/mediadiscoverybackend.cpp2
-rw-r--r--src/plugins/ivimedia/media_simulator/mediadiscoverybackend.h4
-rw-r--r--src/plugins/ivimedia/media_simulator/mediaindexerbackend.cpp224
-rw-r--r--src/plugins/ivimedia/media_simulator/mediaindexerbackend.h87
-rw-r--r--src/plugins/ivimedia/media_simulator/mediaplugin.cpp10
-rw-r--r--src/plugins/ivimedia/media_simulator/mediaplugin.h2
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
diff --git a/qtivi.pro b/qtivi.pro
index abc2858..1c1fc6b 100644
--- a/qtivi.pro
+++ b/qtivi.pro
@@ -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;
};