diff --git a/3rdparty/libprojectm/CMakeLists.txt b/3rdparty/libprojectm/CMakeLists.txt
index 98d7b4468..f543f0041 100644
--- a/3rdparty/libprojectm/CMakeLists.txt
+++ b/3rdparty/libprojectm/CMakeLists.txt
@@ -5,6 +5,7 @@ SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The projectM core library.")
include(CheckCXXCompilerFlag)
cmake_policy(SET CMP0005 OLD)
+cmake_policy(SET CMP0017 OLD)
set(USE_DEVIL OFF)
diff --git a/3rdparty/qsqlite/CMakeLists.txt b/3rdparty/qsqlite/CMakeLists.txt
index d391b6602..d6d174042 100644
--- a/3rdparty/qsqlite/CMakeLists.txt
+++ b/3rdparty/qsqlite/CMakeLists.txt
@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 2.6)
+add_definitions(-DQT_STATICPLUGIN)
+
# Source files
set(SQLITE-SOURCES
qsql_sqlite.cpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e1ffbca1d..1f8c7676b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -279,7 +279,6 @@ endif(ENABLE_REMOTE AND HAVE_GNUTLS AND HAVE_PJSIP)
set(HAVE_STATIC_SQLITE ${STATIC_SQLITE})
if(STATIC_SQLITE)
message(STATUS "Building static qsqlite plugin")
- add_definitions(-DQT_STATICPLUGIN)
add_subdirectory(3rdparty/qsqlite)
include_directories("3rdparty/qsqlite")
endif(STATIC_SQLITE)
@@ -381,6 +380,13 @@ if(HAVE_SPOTIFY_BLOB)
add_subdirectory(spotifyblob/blob)
endif(HAVE_SPOTIFY_BLOB)
+# This goes after everything else because KDE fucks everything else up with its
+# cmake includes.
+find_package(KDE4 4.3.60)
+if(KDE4_PLASMA_LIBS)
+ add_subdirectory(plasmarunner)
+endif(KDE4_PLASMA_LIBS)
+
# Uninstall support
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
diff --git a/data/clementineplasmarunner.qrc b/data/clementineplasmarunner.qrc
new file mode 100644
index 000000000..a4ff71d9c
--- /dev/null
+++ b/data/clementineplasmarunner.qrc
@@ -0,0 +1,5 @@
+
+
+ nocover.png
+
+
diff --git a/plasmarunner/CMakeLists.txt b/plasmarunner/CMakeLists.txt
new file mode 100644
index 000000000..a0f993328
--- /dev/null
+++ b/plasmarunner/CMakeLists.txt
@@ -0,0 +1,33 @@
+include(KDE4Defaults)
+include(MacroLibrary)
+
+add_definitions(${KDE4_DEFINITIONS})
+include_directories(${CMAKE_SOURCE_DIR})
+include_directories(${CMAKE_BINARY_DIR}/src)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+include_directories(${KDE4_INCLUDES})
+
+set(SOURCES
+ clementinerunner.cpp
+ ../src/globalsearch/common.cpp
+)
+
+set(RESOURCES
+ ../data/clementineplasmarunner.qrc
+)
+
+list(APPEND QT_DBUSXML2CPP_EXECUTABLE -i src/globalsearch/common.h)
+
+qt4_add_dbus_interface(SOURCES
+ ${CMAKE_SOURCE_DIR}/src/dbus/org.clementineplayer.GlobalSearch.xml
+ globalsearchinterface)
+qt4_add_resources(QRC ${RESOURCES})
+kde4_add_plugin(plasma_runner_clementine ${SOURCES} ${QRC})
+
+target_link_libraries(plasma_runner_clementine ${KDE4_PLASMA_LIBS})
+
+# Install the library and .desktop file
+install(TARGETS plasma_runner_clementine DESTINATION ${PLUGIN_INSTALL_DIR})
+install(FILES plasma-runner-clementine.desktop DESTINATION ${SERVICES_INSTALL_DIR})
+
diff --git a/plasmarunner/clementinerunner.cpp b/plasmarunner/clementinerunner.cpp
new file mode 100644
index 000000000..30f085e24
--- /dev/null
+++ b/plasmarunner/clementinerunner.cpp
@@ -0,0 +1,295 @@
+/* This file is part of Clementine.
+ Copyright 2011, David Sansome
+
+ Clementine 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 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 Clementine. If not, see .
+*/
+
+#include "clementinerunner.h"
+#include "globalsearchinterface.h"
+
+#include
+#include
+#include
+
+#include
+
+const char* ClementineRunner::kDbusService = "org.mpris.clementine";
+const char* ClementineRunner::kDbusPath = "/GlobalSearch";
+
+
+ClementineRunner::ClementineRunner(QObject* parent, const QVariantList& args)
+ : Plasma::AbstractRunner(parent, args),
+ interface_(NULL)
+{
+ qDBusRegisterMetaType();
+ qDBusRegisterMetaType();
+
+ Q_INIT_RESOURCE(clementineplasmarunner);
+
+ nocover_ = QIcon(":/clementineplasmarunner/nocover.png");
+
+ setIgnoredTypes(Plasma::RunnerContext::NetworkLocation |
+ Plasma::RunnerContext::FileSystem);
+ setSpeed(SlowSpeed);
+ setPriority(LowPriority);
+ setHasRunOptions(true);
+
+ Plasma::RunnerSyntax syntax = Plasma::RunnerSyntax("", tr("Search music"));
+ syntax.addExampleQuery("foo fighters");
+ addSyntax(syntax);
+
+ QDBusConnection bus = QDBusConnection::sessionBus();
+ bus.connect(
+ kDbusService, kDbusPath,
+ OrgClementineplayerGlobalSearchInterface::staticInterfaceName(),
+ "SearchFinished", "i", this, SLOT(SearchFinished(int)));
+ bus.connect(
+ kDbusService, kDbusPath,
+ OrgClementineplayerGlobalSearchInterface::staticInterfaceName(),
+ "ResultsAvailable", "ia(ibsiiissssbi)",
+ this, SLOT(ResultsAvailable(int,GlobalSearchServiceResultList)));
+ bus.connect(
+ kDbusService, kDbusPath,
+ OrgClementineplayerGlobalSearchInterface::staticInterfaceName(),
+ "ArtLoaded", "iay", this, SLOT(ArtLoaded(int,QByteArray)));
+}
+
+void ClementineRunner::match(Plasma::RunnerContext& context) {
+
+ if (context.query().length() < 3)
+ return;
+
+ if (!interface_) {
+ interface_ = new OrgClementineplayerGlobalSearchInterface(
+ kDbusService, kDbusPath, QDBusConnection::sessionBus());
+ }
+
+ int id = 0;
+ PendingQuery query;
+ query.results_mutex_.lock();
+
+ // Start the search
+ {
+ QMutexLocker l(&pending_mutex_);
+ QDBusPendingReply reply = interface_->StartSearch(context.query(), true);
+ reply.waitForFinished();
+
+ if (!reply.isValid()) {
+ qDebug() << reply.error();
+ return;
+ }
+ id = reply.value();
+
+ pending_queries_[id] = &query;
+ }
+
+ query.results_mutex_.unlock();
+
+ // Wait for results to arrive
+ forever {
+ query.results_semaphore_.acquire();
+
+ // If the user closed the query then stop early.
+ if (!context.isValid())
+ break;
+
+ // Take the next result on the list
+ GlobalSearchServiceResult result;
+ {
+ QMutexLocker l(&query.results_mutex_);
+ if (query.results_.isEmpty() && query.finished_)
+ break;
+
+ result = query.results_.takeFirst();
+ }
+
+ // Create a match for the result.
+ Plasma::QueryMatch match(this);
+ FillMatch(result, &match);
+
+ // Emit the match
+ context.addMatch(QString(), match);
+ }
+
+ // Remove the pending search
+ {
+ QMutexLocker l(&pending_mutex_);
+ pending_queries_.remove(id);
+ }
+}
+
+void ClementineRunner::FillMatch(const GlobalSearchServiceResult& result,
+ Plasma::QueryMatch* match) const {
+ QString line[2];
+
+ switch (result.type_) {
+ case globalsearch::Type_Track:
+ case globalsearch::Type_Stream: {
+ line[0] = result.title_;
+
+ if (!result.artist_.isEmpty()) {
+ line[1] += result.artist_;
+ } else if (!result.album_artist_.isEmpty()) {
+ line[1] += result.album_artist_;
+ }
+
+ if (!result.album_.isEmpty()) {
+ line[1] += " - " + result.album_;
+ }
+
+ if (result.track_ > 0) {
+ line[1] += " - " + tr("track %1").arg(result.track_);
+ }
+
+ break;
+ }
+
+ case globalsearch::Type_Album: {
+ if (!result.album_artist_.isEmpty())
+ line[0] += result.album_artist_;
+ else if (result.is_compilation_)
+ line[0] += tr("Various Artists");
+ else if (!result.artist_.isEmpty())
+ line[0] += result.artist_;
+ else
+ line[0] += tr("Unknown");
+
+ // Dash
+ line[0] += " - ";
+
+ // Album
+ if (result.album_.isEmpty())
+ line[0] += tr("Unknown");
+ else
+ line[0] += result.album_;
+
+ if (result.album_size_ > 1)
+ line[1] = tr("Album with %1 tracks").arg(result.album_size_);
+
+ break;
+ }
+ }
+
+ match->setType(Plasma::QueryMatch::CompletionMatch);
+ match->setText(line[0]);
+ match->setSubtext(line[1]);
+ match->setRelevance(ResultRelevance(result));
+
+ if (!result.image_.isNull()) {
+ match->setIcon(result.image_);
+ } else {
+ match->setIcon(nocover_);
+ }
+}
+
+void ClementineRunner::run(const Plasma::RunnerContext& context, const Plasma::QueryMatch& match) {
+ // TODO
+ qDebug() << __PRETTY_FUNCTION__;
+}
+
+qreal ClementineRunner::ResultRelevance(const GlobalSearchServiceResult& result) const {
+ // Plasma sorts results by a qreal that we provide. We have to do some dumb
+ // maths to create a qreal for the result such that it will produce the same
+ // sorting as you'd get in clementine.
+
+ // Clementine sorts by:
+ // provider
+ // match quality
+ // type
+ // title (for tracks and streams)
+ // artist/album (for albums)
+
+ qreal ret =
+ 10000 * qreal(result.provider_order_) / 10.0 +
+ 100 * qreal(globalsearch::Quality_None + 1 - result.match_quality_) +
+ 10 * qreal(globalsearch::Type_Album + 1 - result.type_);
+
+ return ret;
+}
+
+void ClementineRunner::ResultsAvailable(int id, GlobalSearchServiceResultList results) {
+ // Lock the mutex and add the results to the list.
+ QMutexLocker l(&pending_mutex_);
+ PendingMap::iterator it = pending_queries_.find(id);
+ if (it == pending_queries_.end())
+ return;
+
+ (*it)->provider_order_ ++;
+
+ QMutexLocker result_l(&(*it)->results_mutex_);
+ foreach (GlobalSearchServiceResult result, results) {
+ result.provider_order_ = (*it)->provider_order_;
+
+ if (result.art_on_the_way_) {
+ // Brace yourselves, art is coming.
+ (*it)->results_waiting_for_art_ << result;
+ } else {
+ (*it)->results_.append(results);
+ (*it)->results_semaphore_.release();
+ }
+ }
+}
+
+void ClementineRunner::SearchFinished(int id) {
+ QMutexLocker l(&pending_mutex_);
+ PendingMap::iterator it = pending_queries_.find(id);
+ if (it == pending_queries_.end())
+ return;
+
+ (*it)->finished_signal_emitted_ = true;
+
+ if ((*it)->results_waiting_for_art_.isEmpty()) {
+ QMutexLocker result_l(&(*it)->results_mutex_);
+ (*it)->finished_ = true;
+ (*it)->results_semaphore_.release();
+ }
+}
+
+void ClementineRunner::ArtLoaded(int result_id, const QByteArray& image_data) {
+ QMutexLocker l(&pending_mutex_);
+
+ // Find a query that has a result with this ID waiting for art
+ foreach (PendingQuery* query, pending_queries_.values()) {
+ GlobalSearchServiceResultList::iterator it;
+ for (it = query->results_waiting_for_art_.begin() ;
+ it != query->results_waiting_for_art_.end() ; ++it) {
+ if (it->result_id_ == result_id) {
+ break;
+ }
+ }
+
+ if (it == query->results_waiting_for_art_.end())
+ continue;
+
+ // The API is stupid so we have to create the QIcon here on the GUI thread.
+ if (!image_data.isEmpty()) {
+ QImage image;
+ if (image.loadFromData(image_data)) {
+ it->image_ = QIcon(QPixmap::fromImage(image));
+ }
+ }
+
+ // Add the art to this result and remote it from the waiting list
+ QMutexLocker result_l(&query->results_mutex_);
+ query->results_ << *it;
+ query->results_waiting_for_art_.erase(it);
+ query->finished_ =
+ query->finished_signal_emitted_ &&
+ query->results_waiting_for_art_.isEmpty();
+ query->results_semaphore_.release(query->finished_ ? 2 : 1);
+ break;
+ }
+}
+
+K_EXPORT_PLASMA_RUNNER(clementine, ClementineRunner)
diff --git a/plasmarunner/clementinerunner.h b/plasmarunner/clementinerunner.h
new file mode 100644
index 000000000..0775cbbb8
--- /dev/null
+++ b/plasmarunner/clementinerunner.h
@@ -0,0 +1,83 @@
+/* This file is part of Clementine.
+ Copyright 2011, David Sansome
+
+ Clementine 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 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 Clementine. If not, see .
+*/
+
+#ifndef CLEMENTINERUNNER_H
+#define CLEMENTINERUNNER_H
+
+#include "src/globalsearch/common.h"
+
+#include
+
+#include
+
+class OrgClementineplayerGlobalSearchInterface;
+
+class ClementineRunner : public Plasma::AbstractRunner {
+ Q_OBJECT
+
+public:
+ ClementineRunner(QObject* parent, const QVariantList& args);
+
+ static const char* kDbusService;
+ static const char* kDbusPath;
+
+ void match(Plasma::RunnerContext& context);
+ void run(const Plasma::RunnerContext& context, const Plasma::QueryMatch& match);
+
+private slots:
+ void ResultsAvailable(int id, GlobalSearchServiceResultList results);
+ void SearchFinished(int id);
+ void ArtLoaded(int result_id, const QByteArray& image_data);
+
+private:
+ struct PendingQuery {
+ PendingQuery()
+ : provider_order_(0),
+ finished_signal_emitted_(false),
+ finished_(false)
+ {}
+
+ // The main thread is the only one to access these variables.
+ int provider_order_;
+ GlobalSearchServiceResultList results_waiting_for_art_;
+ bool finished_signal_emitted_;
+
+ // This list contains results that are finished and waiting to be processed
+ // by the match() thread. results_mutex_ locks results_ and
+ // results_semaphore_ is released once for each result.
+ GlobalSearchServiceResultList results_;
+ QMutex results_mutex_;
+ QSemaphore results_semaphore_;
+ bool finished_;
+ };
+ typedef QMap PendingMap;
+
+ qreal ResultRelevance(const GlobalSearchServiceResult& result) const;
+ void FillMatch(const GlobalSearchServiceResult& result,
+ Plasma::QueryMatch* match) const;
+
+private:
+ OrgClementineplayerGlobalSearchInterface* interface_;
+
+ QIcon nocover_;
+
+ // pending_mutex_ locks any access to the PendingMap.
+ QMutex pending_mutex_;
+ PendingMap pending_queries_;
+};
+
+#endif // CLEMENTINERUNNER_H
diff --git a/plasmarunner/plasma-runner-clementine.desktop b/plasmarunner/plasma-runner-clementine.desktop
new file mode 100644
index 000000000..eddf71016
--- /dev/null
+++ b/plasmarunner/plasma-runner-clementine.desktop
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Name=Clementine
+Icon=clementine
+Comment=Clementine global music search
+Type=Service
+ServiceTypes=Plasma/Runner
+
+X-KDE-Library=plasma_runner_clementine
+X-KDE-PluginInfo-Author=David Sansome
+X-KDE-PluginInfo-Email=me@davidsansome.com
+X-KDE-PluginInfo-Name=clementine
+X-KDE-PluginInfo-Version=1.0
+X-KDE-PluginInfo-Website=http://www.clementine-player.org/
+X-KDE-PluginInfo-Category=Audio
+X-KDE-PluginInfo-Depends=
+X-KDE-PluginInfo-License=GPL
+X-KDE-PluginInfo-EnabledByDefault=true
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7c4416ba2..4b12d41fe 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -116,6 +116,7 @@ set(SOURCES
engines/gstenginepipeline.cpp
engines/gstelementdeleter.cpp
+ globalsearch/common.cpp
globalsearch/digitallyimportedsearchprovider.cpp
globalsearch/globalsearch.cpp
globalsearch/globalsearchitemdelegate.cpp
@@ -779,7 +780,6 @@ if(HAVE_DBUS)
dbus/org.gnome.SettingsDaemon.MediaKeys.xml
dbus/gnomesettingsdaemon)
-
# DeviceKit DBUS interfaces
if(HAVE_DEVICEKIT)
qt4_add_dbus_interface(SOURCES
@@ -790,6 +790,16 @@ if(HAVE_DBUS)
dbus/udisksdevice)
endif(HAVE_DEVICEKIT)
+ # Global search interface
+ qt4_add_dbus_adaptor(SOURCES
+ dbus/org.clementineplayer.GlobalSearch.xml
+ globalsearch/globalsearchservice.h GlobalSearchService
+ globalsearch/globalsearchadaptor)
+
+ # Global search source
+ list(APPEND SOURCES globalsearch/globalsearchservice.cpp)
+ list(APPEND HEADERS globalsearch/globalsearchservice.h)
+
# MPRIS source
list(APPEND SOURCES core/mpris.cpp core/mpris1.cpp core/mpris2.cpp)
list(APPEND HEADERS core/mpris.h core/mpris1.h core/mpris2.h)
diff --git a/src/core/mpris2.cpp b/src/core/mpris2.cpp
index 6154de3e9..c36d06641 100644
--- a/src/core/mpris2.cpp
+++ b/src/core/mpris2.cpp
@@ -305,25 +305,11 @@ void Mpris2::CurrentSongChanged(const Song& song) {
// ... and we add the cover information later, when it's available.
void Mpris2::ArtLoaded(const Song& song, const QString& art_uri) {
last_metadata_ = QVariantMap();
+ song.ToXesam(&last_metadata_);
using mpris::AddMetadata;
AddMetadata("mpris:trackid", current_track_id(), &last_metadata_);
- AddMetadata("xesam:url", song.url().toString(), &last_metadata_);
- AddMetadata("xesam:title", song.PrettyTitle(), &last_metadata_);
- AddMetadataAsList("xesam:artist", song.artist(), &last_metadata_);
- AddMetadata("xesam:album", song.album(), &last_metadata_);
- AddMetadataAsList("xesam:albumArtist", song.albumartist(), &last_metadata_);
- AddMetadata("mpris:length", song.length_nanosec() / kNsecPerUsec, &last_metadata_);
- AddMetadata("xesam:trackNumber", song.track(), &last_metadata_);
- AddMetadataAsList("xesam:genre", song.genre(), &last_metadata_);
- AddMetadata("xesam:discNumber", song.disc(), &last_metadata_);
- AddMetadataAsList("xesam:comment", song.comment(), &last_metadata_);
- AddMetadata("xesam:contentCreated", AsMPRISDateTimeType(song.ctime()), &last_metadata_);
- AddMetadata("xesam:lastUsed", AsMPRISDateTimeType(song.lastplayed()), &last_metadata_);
- AddMetadata("xesam:audioBPM", song.bpm(), &last_metadata_);
- AddMetadataAsList("xesam:composer", song.composer(), &last_metadata_);
- AddMetadata("xesam:useCount", song.playcount(), &last_metadata_);
- AddMetadata("xesam:autoRating", song.score(), &last_metadata_);
+
if (song.rating() != -1.0) {
AddMetadata("rating", song.rating() * 5, &last_metadata_);
}
diff --git a/src/core/mpris2.h b/src/core/mpris2.h
index 445db8b2d..3d7f33e36 100644
--- a/src/core/mpris2.h
+++ b/src/core/mpris2.h
@@ -175,10 +175,6 @@ private:
Mpris1* mpris1_;
};
-inline QString AsMPRISDateTimeType(uint time) {
- return time != -1 ? QDateTime::fromTime_t(time).toString(Qt::ISODate) : "";
-}
-
} // namespace mpris
#endif
diff --git a/src/core/mpris_common.h b/src/core/mpris_common.h
index 361aaff65..218c3e3fc 100644
--- a/src/core/mpris_common.h
+++ b/src/core/mpris_common.h
@@ -41,6 +41,10 @@ inline void AddMetadata(const QString& key, const QDateTime& metadata, QVariantM
if (metadata.isValid()) (*map)[key] = metadata;
}
+inline QString AsMPRISDateTimeType(uint time) {
+ return time != -1 ? QDateTime::fromTime_t(time).toString(Qt::ISODate) : "";
+}
+
} // namespace mpris
#endif // MPRIS_COMMON_H
diff --git a/src/core/song.cpp b/src/core/song.cpp
index 993343d77..2e1f58628 100644
--- a/src/core/song.cpp
+++ b/src/core/song.cpp
@@ -18,6 +18,7 @@
#include "fmpsparser.h"
#include "song.h"
#include "core/logging.h"
+#include "core/mpris_common.h"
#include
@@ -1357,3 +1358,29 @@ bool Song::IsOnSameAlbum(const Song& other) const {
return album() == other.album() && artist() == other.artist();
}
+
+void Song::ToXesam(QVariantMap* map) const {
+ using mpris::AddMetadata;
+ using mpris::AddMetadataAsList;
+ using mpris::AsMPRISDateTimeType;
+
+ AddMetadata("xesam:url", url().toString(), map);
+ AddMetadata("xesam:title", PrettyTitle(), map);
+ AddMetadataAsList("xesam:artist", artist(), map);
+ AddMetadata("xesam:album", album(), map);
+ AddMetadataAsList("xesam:albumArtist", albumartist(), map);
+ AddMetadata("mpris:length", length_nanosec() / kNsecPerUsec, map);
+ AddMetadata("xesam:trackNumber", track(), map);
+ AddMetadataAsList("xesam:genre", genre(), map);
+ AddMetadata("xesam:discNumber", disc(), map);
+ AddMetadataAsList("xesam:comment", comment(), map);
+ AddMetadata("xesam:contentCreated", AsMPRISDateTimeType(ctime()), map);
+ AddMetadata("xesam:lastUsed", AsMPRISDateTimeType(lastplayed()), map);
+ AddMetadata("xesam:audioBPM", bpm(), map);
+ AddMetadataAsList("xesam:composer", composer(), map);
+ AddMetadata("xesam:useCount", playcount(), map);
+ AddMetadata("xesam:autoRating", score(), map);
+ if (rating() != -1.0) {
+ AddMetadata("xesam:userRating", rating(), map);
+ }
+}
diff --git a/src/core/song.h b/src/core/song.h
index 0374b0e42..ee3396261 100644
--- a/src/core/song.h
+++ b/src/core/song.h
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
#include
@@ -63,6 +64,7 @@ namespace TagLib {
}
}
+
class FileRefFactory {
public:
virtual ~FileRefFactory() {}
@@ -161,6 +163,7 @@ class Song {
#ifdef HAVE_LIBLASTFM
void ToLastFM(lastfm::Track* track) const;
#endif
+ void ToXesam(QVariantMap* map) const;
// Simple accessors
bool is_valid() const { return d->valid_; }
diff --git a/src/dbus/org.clementineplayer.GlobalSearch.xml b/src/dbus/org.clementineplayer.GlobalSearch.xml
new file mode 100644
index 000000000..13fb04241
--- /dev/null
+++ b/src/dbus/org.clementineplayer.GlobalSearch.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/globalsearch/common.cpp b/src/globalsearch/common.cpp
new file mode 100644
index 000000000..df7711d50
--- /dev/null
+++ b/src/globalsearch/common.cpp
@@ -0,0 +1,66 @@
+/* This file is part of Clementine.
+ Copyright 2011, David Sansome
+
+ Clementine 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 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 Clementine. If not, see .
+*/
+
+#include "common.h"
+
+#ifdef HAVE_DBUS
+
+QDBusArgument& operator <<(QDBusArgument& arg, const GlobalSearchServiceResult& result) {
+ arg.beginStructure();
+ arg << result.result_id_
+ << result.art_on_the_way_
+ << result.provider_name_
+ << result.type_
+ << result.match_quality_
+ << result.album_size_
+ << result.title_
+ << result.artist_
+ << result.album_
+ << result.album_artist_
+ << result.is_compilation_
+ << result.track_;
+ arg.endStructure();
+
+ return arg;
+}
+
+const QDBusArgument& operator >>(const QDBusArgument& arg, GlobalSearchServiceResult& result) {
+ int type;
+ int match_quality;
+
+ arg.beginStructure();
+ arg >> result.result_id_
+ >> result.art_on_the_way_
+ >> result.provider_name_
+ >> type
+ >> match_quality
+ >> result.album_size_
+ >> result.title_
+ >> result.artist_
+ >> result.album_
+ >> result.album_artist_
+ >> result.is_compilation_
+ >> result.track_;
+ arg.endStructure();
+
+ result.type_ = static_cast(type);
+ result.match_quality_ = static_cast(match_quality);
+
+ return arg;
+}
+
+#endif // HAVE_DBUS
diff --git a/src/globalsearch/common.h b/src/globalsearch/common.h
new file mode 100644
index 000000000..ce9d2fdaa
--- /dev/null
+++ b/src/globalsearch/common.h
@@ -0,0 +1,92 @@
+/* This file is part of Clementine.
+ Copyright 2011, David Sansome
+
+ Clementine 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 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 Clementine. If not, see .
+*/
+
+#ifndef GLOBALSEARCHSERVICERESULT_H
+#define GLOBALSEARCHSERVICERESULT_H
+
+// This file contains definitions that are shared between Clementine and any
+// external applications that need to do global searches over DBus.
+
+#include "config.h"
+
+#ifdef HAVE_DBUS
+# include
+#endif
+
+#include
+
+namespace globalsearch {
+
+// The order of types here is the order they'll appear in the UI.
+enum Type {
+ Type_Track = 0,
+ Type_Stream,
+ Type_Album
+};
+
+enum MatchQuality {
+ // A token in the search string matched at the beginning of the song
+ // metadata.
+ Quality_AtStart = 0,
+
+ // A token matched somewhere else.
+ Quality_Middle,
+
+ Quality_None
+};
+
+} // namespace globalsearch
+
+
+#ifdef HAVE_DBUS
+
+struct GlobalSearchServiceResult {
+ // When adding new fields to this struct remember to update the dbus signature
+ // which is duplicated in the xml specification and in clementinerunner.cpp
+
+ int result_id_;
+ bool art_on_the_way_;
+
+ QString provider_name_;
+ globalsearch::Type type_;
+ globalsearch::MatchQuality match_quality_;
+
+ int album_size_;
+
+ QString title_;
+ QString artist_;
+ QString album_;
+ QString album_artist_;
+ bool is_compilation_;
+ int track_;
+
+ // Not included in the dbus emission.
+ QIcon image_;
+ int provider_order_;
+};
+typedef QList GlobalSearchServiceResultList;
+
+Q_DECLARE_METATYPE(GlobalSearchServiceResult)
+Q_DECLARE_METATYPE(GlobalSearchServiceResultList)
+
+QDBusArgument& operator <<(QDBusArgument& arg, const GlobalSearchServiceResult& result);
+const QDBusArgument& operator >>(const QDBusArgument& arg, GlobalSearchServiceResult& result);
+
+#endif // HAVE_DBUS
+
+
+#endif // GLOBALSEARCHSERVICERESULT_H
diff --git a/src/globalsearch/globalsearchitemdelegate.cpp b/src/globalsearch/globalsearchitemdelegate.cpp
index d737022b5..ded793dd9 100644
--- a/src/globalsearch/globalsearchitemdelegate.cpp
+++ b/src/globalsearch/globalsearchitemdelegate.cpp
@@ -88,14 +88,14 @@ void GlobalSearchItemDelegate::paint(QPainter* p,
QString count;
switch (result.type_) {
- case SearchProvider::Result::Type_Track:
+ case globalsearch::Type_Track:
break;
- case SearchProvider::Result::Type_Stream:
+ case globalsearch::Type_Stream:
count = QString::fromUtf8("∞");
break;
- case SearchProvider::Result::Type_Album:
+ case globalsearch::Type_Album:
if (result.album_size_ <= 0)
count = "-";
else
@@ -130,8 +130,8 @@ void GlobalSearchItemDelegate::paint(QPainter* p,
// The text we draw depends on the type of result.
switch (result.type_) {
- case SearchProvider::Result::Type_Track:
- case SearchProvider::Result::Type_Stream: {
+ case globalsearch::Type_Track:
+ case globalsearch::Type_Stream: {
// Title
line_1 += m.title() + " ";
@@ -153,7 +153,7 @@ void GlobalSearchItemDelegate::paint(QPainter* p,
break;
}
- case SearchProvider::Result::Type_Album: {
+ case globalsearch::Type_Album: {
// Line 1 is Artist - Album
// Artist
if (!m.albumartist().isEmpty())
diff --git a/src/globalsearch/globalsearchservice.cpp b/src/globalsearch/globalsearchservice.cpp
new file mode 100644
index 000000000..3ab6b7e0d
--- /dev/null
+++ b/src/globalsearch/globalsearchservice.cpp
@@ -0,0 +1,129 @@
+/* This file is part of Clementine.
+ Copyright 2011, David Sansome
+
+ Clementine 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 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 Clementine. If not, see .
+*/
+
+#include "globalsearch.h"
+#include "globalsearchservice.h"
+#include "globalsearch/globalsearchadaptor.h"
+#include "core/logging.h"
+#include "core/mpris_common.h"
+
+
+GlobalSearchService::GlobalSearchService(GlobalSearch* engine, QObject* parent)
+ : QObject(parent),
+ engine_(engine)
+{
+ qDBusRegisterMetaType();
+ qDBusRegisterMetaType();
+
+ new GlobalSearchAdaptor(this);
+ QDBusConnection::sessionBus().registerObject("/GlobalSearch", this);
+
+ connect(engine_, SIGNAL(ResultsAvailable(int,SearchProvider::ResultList)),
+ this, SLOT(ResultsAvailableSlot(int,SearchProvider::ResultList)),
+ Qt::QueuedConnection);
+ connect(engine_, SIGNAL(SearchFinished(int)),
+ this, SLOT(SearchFinishedSlot(int)),
+ Qt::QueuedConnection);
+ connect(engine_, SIGNAL(ArtLoaded(int,QPixmap)),
+ this, SLOT(ArtLoadedSlot(int,QPixmap)),
+ Qt::QueuedConnection);
+}
+
+int GlobalSearchService::StartSearch(const QString& query, bool prefetch_art) {
+ PendingSearch pending_search;
+ pending_search.prefetch_art_ = prefetch_art;
+
+ const int id = engine_->SearchAsync(query);
+ pending_searches_[id] = pending_search;
+ return id;
+}
+
+void GlobalSearchService::CancelSearch(int id) {
+ if (!pending_searches_.contains(id))
+ return;
+
+ engine_->CancelSearch(id);
+ pending_searches_.remove(id);
+}
+
+void GlobalSearchService::ResultsAvailableSlot(int id, const SearchProvider::ResultList& results) {
+ if (!pending_searches_.contains(id))
+ return;
+
+ const PendingSearch& pending = pending_searches_[id];
+
+ GlobalSearchServiceResultList ret;
+ foreach (const SearchProvider::Result& result, results) {
+ const int result_id = next_result_id_ ++;
+
+ RecentResult& recent = recent_results_[result_id];
+ recent.result_.art_on_the_way_ = false;
+
+ // Prefetch art if it was requested
+ if (pending.prefetch_art_ && !result.provider_->art_is_probably_remote()) {
+ const int art_id = engine_->LoadArtAsync(result);
+ prefetching_art_[art_id] = result_id;
+ recent.result_.art_on_the_way_ = true;
+ }
+
+ // Build the result to send back
+ recent.result_.result_id_ = result_id;
+ recent.result_.provider_name_ = result.provider_->name();
+ recent.result_.type_ = result.type_;
+ recent.result_.match_quality_ = result.match_quality_;
+
+ recent.result_.album_size_ = result.album_size_;
+
+ recent.result_.title_ = result.metadata_.title();
+ recent.result_.artist_ = result.metadata_.artist();
+ recent.result_.album_ = result.metadata_.album();
+ recent.result_.album_artist_ = result.metadata_.albumartist();
+ recent.result_.is_compilation_ = result.metadata_.is_compilation();
+ recent.result_.track_ = result.metadata_.track();
+
+ ret << recent.result_;
+ }
+
+ emit ResultsAvailable(id, ret);
+}
+
+void GlobalSearchService::SearchFinishedSlot(int id) {
+ if (!pending_searches_.contains(id))
+ return;
+
+ emit SearchFinished(id);
+ pending_searches_.remove(id);
+}
+
+void GlobalSearchService::ArtLoadedSlot(int id, const QPixmap& pixmap) {
+ QMap::iterator it = prefetching_art_.find(id);
+ if (it == prefetching_art_.end())
+ return;
+
+ const int result_id = prefetching_art_.take(id);
+ QMap::iterator it2 = recent_results_.find(result_id);
+ if (it2 == recent_results_.end())
+ return;
+
+ // Encode the pixmap as a png
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ pixmap.toImage().save(&buf, "PNG");
+ buf.close();
+
+ emit ArtLoaded(result_id, buf.data());
+}
diff --git a/src/globalsearch/globalsearchservice.h b/src/globalsearch/globalsearchservice.h
new file mode 100644
index 000000000..9d9171ec7
--- /dev/null
+++ b/src/globalsearch/globalsearchservice.h
@@ -0,0 +1,74 @@
+/* This file is part of Clementine.
+ Copyright 2011, David Sansome
+
+ Clementine 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 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 Clementine. If not, see .
+*/
+
+#ifndef GLOBALSEARCHSERVICE_H
+#define GLOBALSEARCHSERVICE_H
+
+#include
+#include
+#include
+
+#include "common.h"
+#include "searchprovider.h"
+
+class GlobalSearch;
+
+class QEventLoop;
+
+
+class GlobalSearchService : public QObject {
+ Q_OBJECT
+
+public:
+ GlobalSearchService(GlobalSearch* engine, QObject* parent = 0);
+
+public slots:
+ int StartSearch(const QString& query, bool prefetch_art);
+ void CancelSearch(int id);
+
+signals:
+ void ResultsAvailable(int id, const GlobalSearchServiceResultList& results);
+ void SearchFinished(int id);
+ void ArtLoaded(int result_id, const QByteArray& image_data);
+
+private slots:
+ void ResultsAvailableSlot(int id, const SearchProvider::ResultList& results);
+ void SearchFinishedSlot(int id);
+ void ArtLoadedSlot(int id, const QPixmap& pixmap);
+
+private:
+ struct PendingSearch {
+ bool prefetch_art_;
+ };
+
+ struct RecentResult {
+ GlobalSearchServiceResult result_;
+ };
+
+ GlobalSearch* engine_;
+
+ // GlobalSearch request ids
+ QMap pending_searches_;
+
+ // Result ids
+ QMap recent_results_;
+ QMap prefetching_art_; // LoadArt id -> result id
+
+ int next_result_id_;
+};
+
+#endif // GLOBALSEARCHSERVICE_H
diff --git a/src/globalsearch/globalsearchsortmodel.cpp b/src/globalsearch/globalsearchsortmodel.cpp
index f50c5fefb..eb79022ae 100644
--- a/src/globalsearch/globalsearchsortmodel.cpp
+++ b/src/globalsearch/globalsearchsortmodel.cpp
@@ -56,11 +56,11 @@ bool GlobalSearchSortModel::lessThan(const QModelIndex& left, const QModelIndex&
// Failing that, compare title, artist and album
switch (r1.type_) {
- case SearchProvider::Result::Type_Track:
- case SearchProvider::Result::Type_Stream:
+ case globalsearch::Type_Track:
+ case globalsearch::Type_Stream:
CompareString(title);
// fallthrough
- case SearchProvider::Result::Type_Album:
+ case globalsearch::Type_Album:
CompareString(artist);
CompareString(album);
break;
diff --git a/src/globalsearch/globalsearchwidget.cpp b/src/globalsearch/globalsearchwidget.cpp
index f0b0829a2..e9b25d173 100644
--- a/src/globalsearch/globalsearchwidget.cpp
+++ b/src/globalsearch/globalsearchwidget.cpp
@@ -616,15 +616,15 @@ GlobalSearchWidget::CombineAction GlobalSearchWidget::CanCombineResults(
(QString::compare(r1.metadata_.field(), r2.metadata_.field(), Qt::CaseInsensitive) != 0)
switch (r1.type_) {
- case SearchProvider::Result::Type_Track:
+ case globalsearch::Type_Track:
if (StringsDiffer(title))
return CannotCombine;
// fallthrough
- case SearchProvider::Result::Type_Album:
+ case globalsearch::Type_Album:
if (StringsDiffer(album) || StringsDiffer(artist))
return CannotCombine;
break;
- case SearchProvider::Result::Type_Stream:
+ case globalsearch::Type_Stream:
if (StringsDiffer(url().toString))
return CannotCombine;
break;
diff --git a/src/globalsearch/groovesharksearchprovider.cpp b/src/globalsearch/groovesharksearchprovider.cpp
index 2a4238809..99df96aa3 100644
--- a/src/globalsearch/groovesharksearchprovider.cpp
+++ b/src/globalsearch/groovesharksearchprovider.cpp
@@ -67,9 +67,9 @@ void GroovesharkSearchProvider::SearchDone(int id, const SongList& songs) {
ResultList ret;
foreach (const Song& song, songs) {
Result result(this);
- result.type_ = Result::Type_Track;
+ result.type_ = globalsearch::Type_Track;
result.metadata_ = song;
- result.match_quality_ = Result::Quality_AtStart;
+ result.match_quality_ = globalsearch::Quality_AtStart;
ret << result;
}
@@ -84,8 +84,8 @@ void GroovesharkSearchProvider::AlbumSearchResult(int id, const SongList& songs)
ResultList ret;
foreach (const Song& s, songs) {
Result result(this);
- result.type_ = Result::Type_Album;
- result.match_quality_ = Result::Quality_AtStart;
+ result.type_ = globalsearch::Type_Album;
+ result.match_quality_ = globalsearch::Quality_AtStart;
result.metadata_ = s;
ret << result;
@@ -120,7 +120,7 @@ void GroovesharkSearchProvider::LoadTracksAsync(int id, const Result& result) {
SongList ret;
switch (result.type_) {
- case Result::Type_Track: {
+ case globalsearch::Type_Track: {
ret << result.metadata_;
SortSongs(&ret);
@@ -131,7 +131,7 @@ void GroovesharkSearchProvider::LoadTracksAsync(int id, const Result& result) {
break;
}
- case Result::Type_Album:
+ case globalsearch::Type_Album:
FetchAlbum(id, result);
break;
diff --git a/src/globalsearch/librarysearchprovider.cpp b/src/globalsearch/librarysearchprovider.cpp
index dad24f589..d088959df 100644
--- a/src/globalsearch/librarysearchprovider.cpp
+++ b/src/globalsearch/librarysearchprovider.cpp
@@ -74,13 +74,13 @@ SearchProvider::ResultList LibrarySearchProvider::Search(int id, const QString&
album_key.prepend(song.artist());
}
- Result::MatchQuality quality = MatchQuality(tokens, song.title());
+ globalsearch::MatchQuality quality = MatchQuality(tokens, song.title());
- if (quality != Result::Quality_None) {
+ if (quality != globalsearch::Quality_None) {
// If the query matched in the song title then we're interested in this
// as an individual song.
Result result(this);
- result.type_ = Result::Type_Track;
+ result.type_ = globalsearch::Type_Track;
result.metadata_ = song;
result.match_quality_ = quality;
ret << result;
@@ -96,7 +96,7 @@ SearchProvider::ResultList LibrarySearchProvider::Search(int id, const QString&
// song title.
foreach (const QString& key, albums_with_non_track_matches) {
Result result(this);
- result.type_ = Result::Type_Album;
+ result.type_ = globalsearch::Type_Album;
result.metadata_ = albums.value(key);
result.album_size_ = albums.count(key);
result.match_quality_ =
@@ -131,12 +131,12 @@ void LibrarySearchProvider::LoadTracksAsync(int id, const Result& result) {
SongList ret;
switch (result.type_) {
- case Result::Type_Track:
+ case globalsearch::Type_Track:
// This is really easy - we just emit the track again.
ret << result.metadata_;
break;
- case Result::Type_Album: {
+ case globalsearch::Type_Album: {
// Find all the songs in this album.
LibraryQuery query;
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
diff --git a/src/globalsearch/searchprovider.cpp b/src/globalsearch/searchprovider.cpp
index 042e78101..a5d30d846 100644
--- a/src/globalsearch/searchprovider.cpp
+++ b/src/globalsearch/searchprovider.cpp
@@ -55,16 +55,16 @@ QStringList SearchProvider::TokenizeQuery(const QString& query) {
return tokens;
}
-SearchProvider::Result::MatchQuality SearchProvider::MatchQuality(
+globalsearch::MatchQuality SearchProvider::MatchQuality(
const QStringList& tokens, const QString& string) {
- Result::MatchQuality ret = Result::Quality_None;
+ globalsearch::MatchQuality ret = globalsearch::Quality_None;
foreach (const QString& token, tokens) {
const int index = string.indexOf(token, 0, Qt::CaseInsensitive);
if (index == 0) {
- return Result::Quality_AtStart;
+ return globalsearch::Quality_AtStart;
} else if (index != -1) {
- ret = Result::Quality_Middle;
+ ret = globalsearch::Quality_Middle;
}
}
diff --git a/src/globalsearch/searchprovider.h b/src/globalsearch/searchprovider.h
index a0a4262bb..f7cf7ea90 100644
--- a/src/globalsearch/searchprovider.h
+++ b/src/globalsearch/searchprovider.h
@@ -23,6 +23,7 @@
#include
#include "core/song.h"
+#include "globalsearch/common.h"
class MimeData;
@@ -39,31 +40,13 @@ public:
Result(SearchProvider* provider = 0)
: provider_(provider), album_size_(0) {}
- // The order of types here is the order they'll appear in the UI.
- enum Type {
- Type_Track = 0,
- Type_Stream,
- Type_Album
- };
-
- enum MatchQuality {
- // A token in the search string matched at the beginning of the song
- // metadata.
- Quality_AtStart = 0,
-
- // A token matched somewhere else.
- Quality_Middle,
-
- Quality_None
- };
-
// This must be set by the provider using the constructor.
SearchProvider* provider_;
// These must be set explicitly by the provider.
- Type type_;
+ globalsearch::Type type_;
+ globalsearch::MatchQuality match_quality_;
Song metadata_;
- MatchQuality match_quality_;
// How many songs in the album - valid only if type == Type_Album.
int album_size_;
@@ -132,7 +115,7 @@ protected:
// useful for figuring out whether you got a result because it matched in
// the song title or the artist/album name.
static QStringList TokenizeQuery(const QString& query);
- static Result::MatchQuality MatchQuality(const QStringList& tokens, const QString& string);
+ static globalsearch::MatchQuality MatchQuality(const QStringList& tokens, const QString& string);
// Sorts a list of songs by disc, then by track.
static void SortSongs(SongList* list);
diff --git a/src/globalsearch/simplesearchprovider.cpp b/src/globalsearch/simplesearchprovider.cpp
index ebc412478..c9dd18bb4 100644
--- a/src/globalsearch/simplesearchprovider.cpp
+++ b/src/globalsearch/simplesearchprovider.cpp
@@ -68,12 +68,12 @@ SearchProvider::ResultList SimpleSearchProvider::Search(int id, const QString& q
QMutexLocker l(&items_mutex_);
foreach (const Item& item, items_) {
Result result(this);
- result.type_ = Result::Type_Stream;
- result.match_quality_ = Result::Quality_None;
+ result.type_ = globalsearch::Type_Stream;
+ result.match_quality_ = globalsearch::Quality_None;
foreach (const QString& token, tokens) {
if (item.keyword_.startsWith(token, Qt::CaseInsensitive)) {
- result.match_quality_ = Result::Quality_AtStart;
+ result.match_quality_ = globalsearch::Quality_AtStart;
continue;
}
@@ -88,17 +88,17 @@ SearchProvider::ResultList SimpleSearchProvider::Search(int id, const QString& q
if (matched_safe_word)
continue;
- result.match_quality_ = Result::Quality_None;
+ result.match_quality_ = globalsearch::Quality_None;
break;
}
- result.match_quality_ = qMin(result.match_quality_, Result::Quality_Middle);
+ result.match_quality_ = qMin(result.match_quality_, globalsearch::Quality_Middle);
}
- if (result.match_quality_ == Result::Quality_Middle) {
+ if (result.match_quality_ == globalsearch::Quality_Middle) {
result.match_quality_ = MatchQuality(tokens, item.metadata_.title());
}
- if (result.match_quality_ != Result::Quality_None) {
+ if (result.match_quality_ != globalsearch::Quality_None) {
result.metadata_ = item.metadata_;
ret << result;
}
diff --git a/src/globalsearch/spotifysearchprovider.cpp b/src/globalsearch/spotifysearchprovider.cpp
index 8b3c8e86a..ee0be977c 100644
--- a/src/globalsearch/spotifysearchprovider.cpp
+++ b/src/globalsearch/spotifysearchprovider.cpp
@@ -88,7 +88,7 @@ void SpotifySearchProvider::SearchFinishedSlot(const spotify_pb::SearchResponse&
const spotify_pb::Track& track = response.result(i);
Result result(this);
- result.type_ = Result::Type_Track;
+ result.type_ = globalsearch::Type_Track;
SpotifyService::SongFromProtobuf(track, &result.metadata_);
result.match_quality_ = MatchQuality(state.tokens_, result.metadata_.title());
@@ -99,7 +99,7 @@ void SpotifySearchProvider::SearchFinishedSlot(const spotify_pb::SearchResponse&
const spotify_pb::Album& album = response.album(i);
Result result(this);
- result.type_ = Result::Type_Album;
+ result.type_ = globalsearch::Type_Album;
SpotifyService::SongFromProtobuf(album.metadata(), &result.metadata_);
result.match_quality_ =
qMin(MatchQuality(state.tokens_, result.metadata_.album()),
@@ -147,14 +147,14 @@ void SpotifySearchProvider::ArtLoadedSlot(const QString& id, const QImage& image
void SpotifySearchProvider::LoadTracksAsync(int id, const Result& result) {
switch (result.type_) {
- case Result::Type_Track: {
+ case globalsearch::Type_Track: {
SongMimeData* mime_data = new SongMimeData;
mime_data->songs = SongList() << result.metadata_;
emit TracksLoaded(id, mime_data);
break;
}
- case Result::Type_Album: {
+ case globalsearch::Type_Album: {
SpotifyServer* s = server();
if (!s) {
emit TracksLoaded(id, NULL);
diff --git a/src/globalsearch/tooltipresultwidget.cpp b/src/globalsearch/tooltipresultwidget.cpp
index c5124b0ad..a399bd5f7 100644
--- a/src/globalsearch/tooltipresultwidget.cpp
+++ b/src/globalsearch/tooltipresultwidget.cpp
@@ -58,11 +58,11 @@ QSize TooltipResultWidget::CalculateSizeHint() const {
bold_metrics_.width(TitleText()) + kBorder);
switch (result_.type_) {
- case SearchProvider::Result::Type_Track:
- case SearchProvider::Result::Type_Stream:
+ case globalsearch::Type_Track:
+ case globalsearch::Type_Stream:
break;
- case SearchProvider::Result::Type_Album:
+ case globalsearch::Type_Album:
if (result_.album_songs_.isEmpty())
break;
@@ -119,11 +119,11 @@ void TooltipResultWidget::paintEvent(QPaintEvent*) {
y += kLineHeight;
switch (result_.type_) {
- case SearchProvider::Result::Type_Track:
- case SearchProvider::Result::Type_Stream:
+ case globalsearch::Type_Track:
+ case globalsearch::Type_Stream:
break;
- case SearchProvider::Result::Type_Album:
+ case globalsearch::Type_Album:
if (result_.album_songs_.isEmpty())
break;
diff --git a/src/main.cpp b/src/main.cpp
index c443308d5..43a064478 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -93,6 +93,7 @@ using boost::scoped_ptr;
#include "core/mpris.h"
#include "core/mpris2.h"
#include "dbus/metatypes.h"
+ #include "globalsearch/globalsearchservice.h"
#include
#include
#include
@@ -220,6 +221,7 @@ int main(int argc, char *argv[]) {
qRegisterMetaTypeStreamOperators >("ColumnAlignmentMap");
qRegisterMetaType("QNetworkCookie");
qRegisterMetaType >("QList");
+ qRegisterMetaType("SearchProvider::Result");
qRegisterMetaType("SearchProvider::ResultList");
qRegisterMetaType("GstBuffer*");
@@ -438,6 +440,8 @@ int main(int argc, char *argv[]) {
QObject::connect(&playlists, SIGNAL(CurrentSongChanged(Song)), &art_loader, SLOT(LoadArt(Song)));
QObject::connect(&art_loader, SIGNAL(ThumbnailLoaded(Song, QString, QImage)),
&osd, SLOT(CoverArtPathReady(Song, QString)));
+
+ GlobalSearchService global_search_service(&global_search);
#endif
// Window