diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b06d974d9..d40204cfb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,268 +1,264 @@ cmake_minimum_required(VERSION 3.4) project(Amarok) # Remove all warnings, ease the porting to cmake 3.x if (POLICY CMP0028) cmake_policy(SET CMP0028 NEW) endif() ############### find_package(PkgConfig REQUIRED) find_package(ECM 1.7.0 REQUIRED CONFIG) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(FeatureSummary) include(ECMInstallIcons) include(ECMSetupVersion) include(ECMAddTests) include(ECMAddAppIcon) include(FindPkgConfig) find_package( Qt5 5.8.0 REQUIRED COMPONENTS Core DBus Gui QuickWidgets Qml Script ScriptTools Sql Svg Test Widgets Xml ) find_package( Qt5 5.8.0 COMPONENTS QuickControls2 ) set_package_properties( Qt5QuickControls2 PROPERTIES TYPE RUNTIME PURPOSE "Needed by the player's context area" ) find_package( KF5 REQUIRED COMPONENTS Archive Codecs CoreAddons DBusAddons Declarative DNSSD GlobalAccel GuiAddons I18n IconThemes KCMUtils KIO NewStuff Notifications NotifyConfig Package Solid TextEditor ThreadWeaver WindowSystem ) find_package( KF5 COMPONENTS Kirigami2 ) set_package_properties( KF5Kirigami2 PROPERTIES TYPE RUNTIME PURPOSE "Needed by the player's context area" ) ############### option(WITH_UTILITIES "Enable building of utilities" ON) option(WITH_PLAYER "Enable building of main Amarok player" ON) option(WITH_MP3Tunes "Enable mp3tunes in the Amarok player, requires multiple extra dependencies" ON) option(WITH_IPOD "Enable iPod support in Amarok" ON) option(WITH_MYSQL_EMBEDDED "Build the embedded database library -- highly recommended" ON) option(WITH_PLAYGROUND "Enable building of playground scripts and applets (WARNING: some of them might have legal issues!)" OFF) ############### Taglib set(TAGLIB_MIN_VERSION "1.7") find_package(Taglib REQUIRED) set_package_properties( Taglib PROPERTIES DESCRIPTION "Support for Audio metadata." URL "http://developer.kde.org/~wheeler/taglib.html" TYPE REQUIRED PURPOSE "Required for tag reading" ) # Check if TagLib is built with ASF and MP4 support include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_INCLUDES "${TAGLIB_INCLUDES}") set(CMAKE_REQUIRED_LIBRARIES "${TAGLIB_LIBRARIES}") check_cxx_source_compiles("#include int main() { TagLib::ASF::Tag tag; return 0;}" TAGLIB_ASF_FOUND) if( NOT TAGLIB_ASF_FOUND ) message(FATAL_ERROR "TagLib does not have ASF support compiled in.") endif() check_cxx_source_compiles("#include int main() { TagLib::MP4::Tag tag(0, 0); return 0;}" TAGLIB_MP4_FOUND) if( NOT TAGLIB_MP4_FOUND ) message(FATAL_ERROR "TagLib does not have MP4 support compiled in.") endif() check_cxx_source_compiles("#include #include #include #include #include using namespace TagLib; int main() { char *s; Mod::Tag tag; Mod::File modfile(s); S3M::File s3mfile(s); IT::File itfile(s); XM::File xmfile(s); return 0; }" TAGLIB_MOD_FOUND) check_cxx_source_compiles("#include int main() { char *s; TagLib::Ogg::Opus::File opusfile(s); return 0;}" TAGLIB_OPUS_FOUND) set(CMAKE_REQUIRED_INCLUDES) set(CMAKE_REQUIRED_LIBRARIES) set(TAGLIB-EXTRAS_MIN_VERSION "1.0") find_package(Taglib-Extras) set(TAGLIB_EXTRAS_FOUND ${TAGLIB-EXTRAS_FOUND}) # we need a c-compatible name for the include file include(CheckTagLibFileName) check_taglib_filename(COMPLEX_TAGLIB_FILENAME) ############### #Needed to conditionally build tests and gui if(BUILD_TESTING) add_definitions(-DDEBUG) endif() if(WITH_DESKTOP_UI) add_definitions(-DDESKTOP_UI) endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fmessage-length=0") if (CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmessage-length=0") if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--as-needed") endif() endif () include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/shared ${CMAKE_CURRENT_BINARY_DIR}/shared ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # Require C++11 # WORKAROUND for Clang bug: http://llvm.org/bugs/show_bug.cgi?id=15651 if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-delayed-template-parsing") endif () add_definitions(-DQT_NO_URL_CAST_FROM_STRING) find_package(Phonon4Qt5 4.6.60 REQUIRED NO_MODULE) find_package( LibLastFm ) set( LIBLASTFM_MIN_VERSION "1.0.0" ) if( LIBLASTFM_FOUND ) if ( ${LIBLASTFM_MIN_VERSION} VERSION_LESS ${LIBLASTFM_VERSION} ) set( LIBLASTFM_FOUND TRUE ) endif() endif() string( TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_TOLOWER ) if( CMAKE_BUILD_TYPE_TOLOWER MATCHES debug ) set( DEBUG_BUILD_TYPE ON ) add_definitions(-Wall -Wextra) endif() # this needs to be here because also code in shared/ needs config.h. This is also the # reason why various checks are above why they belong under if( WITH_PLAYER ) configure_file( shared/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/shared/config.h ) add_subdirectory( data ) add_subdirectory( images ) add_subdirectory( shared ) if( WITH_PLAYER ) find_package(X11) find_package(MySQLAmarok REQUIRED) if( WITH_MYSQL_EMBEDDED ) set( BUILD_MYSQLE_COLLECTION TRUE ) set_package_properties( MYSQLD PROPERTIES DESCRIPTION "Embedded MySQL Libraries" URL "http://www.mysql.com" TYPE REQUIRED ) else() add_definitions( "-DNO_MYSQL_EMBEDDED" ) endif() set_package_properties( MYSQL PROPERTIES DESCRIPTION "MySQL Server Libraries" URL "http://www.mysql.com" TYPE REQUIRED ) # zlib is required for mysql embedded find_package(ZLIB REQUIRED) set_package_properties( ZLIB PROPERTIES DESCRIPTION "zlib" TYPE REQUIRED ) - # QJson is required for the PlaydarCollection - find_package(QJSON) - set_package_properties( QJSON PROPERTIES DESCRIPTION "Qt JSON Parser used for the Playdar Collection" URL "http://qjson.sourceforge.net/" TYPE OPTIONAL ) - # We tell users that we need 1.0.3, but we really check just >= 1.0.0. This is because # upstream forgot to update version in lastfm/global.h, so it looks like 1.0.2. :-( # will be fixed in liblastfm-1.0.4 set( LIBLASTFM_MIN_VERSION "1.0.3" ) set_package_properties( LibLastFm PROPERTIES DESCRIPTION "Enable Last.Fm service, including scrobbling, song submissions, and suggested song dynamic playlists" URL "http://cdn.last.fm/client/liblastfm-${LIBLASTFM_MIN_VERSION}.tar.gz" TYPE OPTIONAL ) find_package(FFmpeg) set_package_properties(FFmpeg PROPERTIES DESCRIPTION "Libraries and tools for handling multimedia data" URL "https://www.ffmpeg.org/" TYPE OPTIONAL PURPOSE "Enable MusicDNS service" ) find_package(LibOFA) set_package_properties(LibOFA PROPERTIES DESCRIPTION "Open-source audio fingerprint by MusicIP" URL "http://code.google.com/p/musicip-libofa/" TYPE OPTIONAL PURPOSE "Enable MusicDNS service" ) ## gpodder Service find_package( Mygpo-qt5 ) set_package_properties( Mygpo-qt5 PROPERTIES DESCRIPTION "Enable gpodder.net service" URL "http://wiki.gpodder.org/wiki/Libmygpo-qt" TYPE OPTIONAL ) if( WITH_IPOD ) find_package(Ipod) set(IPOD_MIN_VERSION "0.8.2") if( IPOD_FOUND AND NOT WIN32 ) if ( ${IPOD_MIN_VERSION} VERSION_LESS ${IPOD_VERSION} ) set( IPOD_FOUND TRUE ) endif() endif() set_package_properties( Ipod PROPERTIES DESCRIPTION "Support Apple iPod/iPad/iPhone audio devices" URL "http://sourceforge.net/projects/gtkpod/" TYPE OPTIONAL ) find_package(GDKPixBuf) set_package_properties( GDKPixBuf PROPERTIES DESCRIPTION "Support for artwork on iPod audio devices via GDK-PixBuf" URL "http://developer.gnome.org/arch/imaging/gdkpixbuf.html" TYPE OPTIONAL ) endif() find_package(Mtp) set_package_properties( Mtp PROPERTIES DESCRIPTION "Enable Support for portable media devices that use the media transfer protocol" URL "http://libmtp.sourceforge.net/" TYPE OPTIONAL ) if( WITH_MP3Tunes ) find_package(CURL) set_package_properties( CURL PROPERTIES DESCRIPTION "Used to transfer data with URLs" URL "https://curl.haxx.se/" TYPE OPTIONAL ) find_package(LibXml2) set_package_properties( LibXml2 PROPERTIES DESCRIPTION "LibXML2 is an XML parser required by mp3tunes." URL "http://www.xmlsoft.org" TYPE OPTIONAL ) find_package(OpenSSL) find_package(Libgcrypt) if ( OPENSSL_FOUND OR LIBGCRYPT_FOUND ) set (_mp3tunes_crypto TRUE ) else () message( SEND_ERROR "Building with mp3tunes support REQUIRES either OpenSSL or GNU Libgcrypt" ) endif () set_package_properties( OpenSSL PROPERTIES DESCRIPTION "OpenSSL or GNU Libgcrypt provides cryptographic functions required by mp3tunes." URL "http://www.openssl.org/ or http://www.gnupg.org/download/#libgcrypt" TYPE OPTIONAL ) set_package_properties( Libgcrypt PROPERTIES DESCRIPTION "OpenSSL or GNU Libgcrypt provides cryptographic functions required by mp3tunes." URL "http://www.openssl.org/ or http://www.gnupg.org/download/#libgcrypt" TYPE OPTIONAL ) find_package(Loudmouth) set_package_properties( Loudmouth PROPERTIES DESCRIPTION "Loudmouth is the communication backend needed by mp3tunes for syncing." URL "http://www.loudmouth-project.org" TYPE OPTIONAL ) include(CheckQtGlib) set_package_properties( QT5_GLIB PROPERTIES DESCRIPTION "Qt5 must be compiled with glib support for mp3tunes" URL "http://www.trolltech.com" TYPE OPTIONAL ) endif() if( WITH_IPOD OR WITH_MP3Tunes ) pkg_search_module( GOBJECT REQUIRED gobject-2.0 ) set_package_properties( GOBJECT PROPERTIES DESCRIPTION "Required by libgpod and mp3tunes." URL "http://www.gtk.org" TYPE OPTIONAL ) pkg_search_module( GLIB2 glib-2.0 ) set_package_properties( GLIB2 PROPERTIES DESCRIPTION "Required by libgpod and mp3tunes" URL "http://www.gtk.org" TYPE OPTIONAL ) endif() find_program( CLAMZ_FOUND clamz PATH ) set_package_properties( CLAMZ PROPERTIES DESCRIPTION "Optional requirement to download songs from the Amazon MP3 store. Highly recommended on Linux, as the official downloader from Amazon is quite broken on many systems." URL "https://code.google.com/p/clamz/" TYPE OPTIONAL ) find_package(PythonInterp) set_package_properties( PYTHON PROPERTIES DESCRIPTION "Required for generating the autocompletion file for the script console" URL "https://www.python.org" TYPE OPTIONAL ) find_package(FFTW3 REQUIRED) if( BUILD_TESTING AND NOT WIN32 ) enable_testing() add_subdirectory( tests ) endif() add_subdirectory( src ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) #Do not remove or modify these. The release script substitutes in for these #comments with appropriate doc and translation directories. #PO_SUBDIR #DOC_SUBDIR endif() if( WITH_UTILITIES ) add_subdirectory( utilities ) endif() if( WITH_PLAYGROUND ) add_subdirectory( playground ) message(STATUS "Included playground subdirectory in configuration") endif() include(CTest) diff --git a/cmake/modules/FindQJSON.cmake b/cmake/modules/FindQJSON.cmake deleted file mode 100644 index fd04ef67b7..0000000000 --- a/cmake/modules/FindQJSON.cmake +++ /dev/null @@ -1,42 +0,0 @@ -# Find QJSON - JSON handling library for Qt -# -# This module defines -# QJSON_FOUND - whether the qsjon library was found -# QJSON_LIBRARIES - the qjson library -# QJSON_INCLUDE_DIR - the include path of the qjson library -# - -if (QJSON_INCLUDE_DIR AND QJSON_LIBRARIES) - - # Already in cache - set (QJSON_FOUND TRUE) - -else () - - if (NOT WIN32) - # use pkg-config to get the values of QJSON_INCLUDE_DIRS - # and QJSON_LIBRARY_DIRS to add as hints to the find commands. - include (FindPkgConfig) - pkg_check_modules (PC_QJSON QJson>=0.5) - endif () - - find_library (QJSON_LIBRARIES - NAMES - qjson - PATHS - ${PC_QJSON_LIBRARY_DIRS} - ${LIB_INSTALL_DIR} - ) - - find_path (QJSON_INCLUDE_DIR - NAMES - qjson/parser.h - PATHS - ${PC_QJSON_INCLUDE_DIRS} - ${INCLUDE_INSTALL_DIR} - ) - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(QJSON DEFAULT_MSG QJSON_LIBRARIES QJSON_INCLUDE_DIR) - -endif () diff --git a/src/core-impl/collections/CMakeLists.txt b/src/core-impl/collections/CMakeLists.txt index 6198d0558e..ba9e96218b 100644 --- a/src/core-impl/collections/CMakeLists.txt +++ b/src/core-impl/collections/CMakeLists.txt @@ -1,23 +1,19 @@ include_directories( ${Amarok_SOURCE_DIR}/src ) set(AMAROK_COLLECTION_SUPPORT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/support) add_subdirectory( daap ) if( NOT WIN32) add_subdirectory( audiocd ) endif() add_subdirectory( ipodcollection ) add_subdirectory( mtpcollection ) add_subdirectory( umscollection ) add_subdirectory( db ) - -# only build playdarcollection if QJson was found -if( QJSON_FOUND ) - add_subdirectory( playdarcollection ) -endif() +add_subdirectory( playdarcollection ) add_subdirectory( upnpcollection ) #add_subdirectory( nepomukcollection ) diff --git a/src/core-impl/collections/playdarcollection/CMakeLists.txt b/src/core-impl/collections/playdarcollection/CMakeLists.txt index 6bbd79babb..711714a2bb 100644 --- a/src/core-impl/collections/playdarcollection/CMakeLists.txt +++ b/src/core-impl/collections/playdarcollection/CMakeLists.txt @@ -1,24 +1,21 @@ -include_directories( ${QJSON_INCLUDE_DIR} ) - set( amarok_collection-playdarcollection_PART_SRCS PlaydarMeta.cpp PlaydarCollection.cpp PlaydarQueryMaker.cpp support/Controller.cpp support/Query.cpp support/ProxyResolver.cpp support/QMFunctionTypes.h ) add_library(amarok_collection-playdarcollection MODULE ${amarok_collection-playdarcollection_PART_SRCS}) target_link_libraries( amarok_collection-playdarcollection amarokcore amaroklib - ${QJSON_LIBRARIES} KF5::ThreadWeaver KF5::KIOCore ) install(TARGETS amarok_collection-playdarcollection DESTINATION ${KDE_INSTALL_PLUGINDIR} ) kcoreaddons_desktop_to_json(amarok_collection-playdarcollection amarok_collection-playdarcollection.desktop SERVICE_TYPES ${CMAKE_SOURCE_DIR}/src/amarok-plugin.desktop) diff --git a/src/core-impl/collections/playdarcollection/PlaydarCollection.cpp b/src/core-impl/collections/playdarcollection/PlaydarCollection.cpp index ff22863c5c..328618db01 100644 --- a/src/core-impl/collections/playdarcollection/PlaydarCollection.cpp +++ b/src/core-impl/collections/playdarcollection/PlaydarCollection.cpp @@ -1,374 +1,373 @@ /**************************************************************************************** * Copyright (c) 2010 Andrew Coder * * * * 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, see . * ****************************************************************************************/ #define DEBUG_PREFIX "PlaydarCollection" #include "PlaydarCollection.h" #include "core/collections/Collection.h" #include "core-impl/collections/support/MemoryCollection.h" #include "core-impl/collections/support/MemoryQueryMaker.h" #include "core-impl/collections/support/CollectionManager.h" #include "core-impl/meta/proxy/MetaProxy.h" #include "PlaydarQueryMaker.h" #include "support/Controller.h" #include "support/ProxyResolver.h" #include "core/support/Debug.h" #include #include #include #include #include #include namespace Collections { PlaydarCollectionFactory::PlaydarCollectionFactory() : CollectionFactory() , m_controller( 0 ) , m_collectionIsManaged( false ) { DEBUG_BLOCK } PlaydarCollectionFactory::~PlaydarCollectionFactory() { DEBUG_BLOCK - CollectionManager::instance()->removeTrackProvider( m_collection.data() ); delete m_collection.data(); delete m_controller; } void PlaydarCollectionFactory::init() { DEBUG_BLOCK m_controller = new Playdar::Controller( this ); connect( m_controller, &Playdar::Controller::playdarReady, this, &PlaydarCollectionFactory::playdarReady ); connect( m_controller, &Playdar::Controller::playdarError, this, &PlaydarCollectionFactory::slotPlaydarError ); checkStatus(); m_collection = new PlaydarCollection; connect( m_collection, &PlaydarCollection::remove, this, &PlaydarCollectionFactory::collectionRemoved ); CollectionManager::instance()->addTrackProvider( m_collection ); m_initialized = true; } void PlaydarCollectionFactory::checkStatus() { m_controller->status(); } void PlaydarCollectionFactory::playdarReady() { DEBUG_BLOCK if( !m_collection ) { m_collection = new PlaydarCollection(); connect( m_collection, &PlaydarCollection::remove, this, &PlaydarCollectionFactory::collectionRemoved ); } if( !m_collectionIsManaged ) { m_collectionIsManaged = true; emit newCollection( m_collection.data() ); } } void PlaydarCollectionFactory::slotPlaydarError( Playdar::Controller::ErrorState error ) { // DEBUG_BLOCK if( error == Playdar::Controller::ErrorState( 1 ) ) { if( m_collection && !m_collectionIsManaged ) CollectionManager::instance()->removeTrackProvider( m_collection.data() ); QTimer::singleShot( 10 * 60 * 1000, this, &PlaydarCollectionFactory::checkStatus ); } } void PlaydarCollectionFactory::collectionRemoved() { DEBUG_BLOCK m_collectionIsManaged = false; QTimer::singleShot( 10000, this, &PlaydarCollectionFactory::checkStatus ); } PlaydarCollection::PlaydarCollection() : m_collectionId( i18n( "Playdar Collection" ) ) , m_memoryCollection( new MemoryCollection ) { DEBUG_BLOCK } PlaydarCollection::~PlaydarCollection() { DEBUG_BLOCK } QueryMaker* PlaydarCollection::queryMaker() { DEBUG_BLOCK PlaydarQueryMaker *freshQueryMaker = new PlaydarQueryMaker( this ); connect( freshQueryMaker, &PlaydarQueryMaker::playdarError, this, &PlaydarCollection::slotPlaydarError ); return freshQueryMaker; } Playlists::UserPlaylistProvider* PlaydarCollection::userPlaylistProvider() { DEBUG_BLOCK return 0; } QString PlaydarCollection::uidUrlProtocol() const { return QString( "playdar" ); } QString PlaydarCollection::collectionId() const { return m_collectionId; } QString PlaydarCollection::prettyName() const { return collectionId(); } QIcon PlaydarCollection::icon() const { return QIcon::fromTheme( "network-server" ); } bool PlaydarCollection::isWritable() const { DEBUG_BLOCK return false; } bool PlaydarCollection::isOrganizable() const { DEBUG_BLOCK return false; } bool PlaydarCollection::possiblyContainsTrack( const QUrl &url ) const { DEBUG_BLOCK QUrlQuery query( url ); if( url.scheme() == uidUrlProtocol() && query.hasQueryItem( QString( "artist" ) ) && query.hasQueryItem( QString( "album" ) ) && query.hasQueryItem( QString( "title" ) ) ) return true; else return false; } Meta::TrackPtr PlaydarCollection::trackForUrl( const QUrl &url ) { DEBUG_BLOCK m_memoryCollection->acquireReadLock(); if( m_memoryCollection->trackMap().contains( url.url() ) ) { Meta::TrackPtr track = m_memoryCollection->trackMap().value( url.url() ); m_memoryCollection->releaseLock(); return track; } else { m_memoryCollection->releaseLock(); MetaProxy::TrackPtr proxyTrack( new MetaProxy::Track( url ) ); proxyTrack->setArtist( QUrlQuery(url).queryItemValue( "artist" ) ); proxyTrack->setAlbum( QUrlQuery(url).queryItemValue( "album" ) ); proxyTrack->setTitle( QUrlQuery(url).queryItemValue( "title" ) ); Playdar::ProxyResolver *proxyResolver = new Playdar::ProxyResolver( this, url, proxyTrack ); connect( proxyResolver, &Playdar::ProxyResolver::playdarError, this, &PlaydarCollection::slotPlaydarError ); return Meta::TrackPtr::staticCast( proxyTrack ); } } bool PlaydarCollection::hasCapabilityInterface( Capabilities::Capability::Type type ) const { //TODO: Make this work once capabilities are set. Q_UNUSED( type ); return false; } Capabilities::Capability* PlaydarCollection::createCapabilityInterface( Capabilities::Capability::Type type ) { //TODO: Make this work once capabilities are set. Q_UNUSED( type ); return 0; } void PlaydarCollection::addNewTrack( Meta::PlaydarTrackPtr track ) { DEBUG_BLOCK m_memoryCollection->acquireReadLock(); if( !m_memoryCollection->trackMap().contains( track->uidUrl() ) ) { m_memoryCollection->releaseLock(); m_memoryCollection->acquireWriteLock(); Meta::PlaydarArtistPtr artistPtr; if( m_memoryCollection->artistMap().contains( track->artist()->name() ) ) { Meta::ArtistPtr artist = m_memoryCollection->artistMap().value( track->artist()->name() ); artistPtr = Meta::PlaydarArtistPtr::staticCast( artist ); } else { artistPtr = track->playdarArtist(); Meta::ArtistPtr artist = Meta::ArtistPtr::staticCast( artistPtr ); m_memoryCollection->addArtist( artist ); } artistPtr->addTrack( track ); track->setArtist( artistPtr ); Meta::PlaydarAlbumPtr albumPtr; if( m_memoryCollection->albumMap().contains( track->album()->name(), artistPtr->name() ) ) { Meta::AlbumPtr album = m_memoryCollection->albumMap().value( track->album()->name(), artistPtr->name() ); albumPtr = Meta::PlaydarAlbumPtr::staticCast( album ); } else { albumPtr = track->playdarAlbum(); albumPtr->setAlbumArtist( artistPtr ); artistPtr->addAlbum( albumPtr ); Meta::AlbumPtr album = Meta::AlbumPtr::staticCast( albumPtr ); m_memoryCollection->addAlbum( album ); } albumPtr->addTrack( track ); track->setAlbum( albumPtr ); Meta::PlaydarGenrePtr genrePtr; if( m_memoryCollection->genreMap().contains( track->genre()->name() ) ) { Meta::GenrePtr genre = m_memoryCollection->genreMap().value( track->genre()->name() ); genrePtr = Meta::PlaydarGenrePtr::staticCast( genre ); } else { genrePtr = track->playdarGenre(); Meta::GenrePtr genre = Meta::GenrePtr::staticCast( genrePtr ); m_memoryCollection->addGenre( genre ); } genrePtr->addTrack( track ); track->setGenre( genrePtr ); Meta::PlaydarComposerPtr composerPtr; if( m_memoryCollection->composerMap().contains( track->composer()->name() ) ) { Meta::ComposerPtr composer = m_memoryCollection->composerMap().value( track->composer()->name() ); composerPtr = Meta::PlaydarComposerPtr::staticCast( composer ); } else { composerPtr = track->playdarComposer(); Meta::ComposerPtr composer = Meta::ComposerPtr::staticCast( composerPtr ); m_memoryCollection->addComposer( composer ); } composerPtr->addTrack( track ); track->setComposer( composerPtr ); Meta::PlaydarYearPtr yearPtr; if( m_memoryCollection->yearMap().contains( track->year()->year() ) ) { Meta::YearPtr year = m_memoryCollection->yearMap().value( track->year()->year() ); yearPtr = Meta::PlaydarYearPtr::staticCast( year ); } else { yearPtr = track->playdarYear(); Meta::YearPtr year = Meta::YearPtr::staticCast( yearPtr ); m_memoryCollection->addYear( year ); } yearPtr->addTrack( track ); track->setYear( yearPtr ); m_memoryCollection->addTrack( Meta::TrackPtr::staticCast( track ) ); foreach( Meta::PlaydarLabelPtr label, track->playdarLabels() ) { m_memoryCollection->addLabelToTrack( Meta::LabelPtr::staticCast( label ), Meta::TrackPtr::staticCast( track ) ); } m_memoryCollection->releaseLock(); emit updated(); } else m_memoryCollection->releaseLock(); } QSharedPointer< MemoryCollection > PlaydarCollection::memoryCollection() { return m_memoryCollection; } void PlaydarCollection::slotPlaydarError( Playdar::Controller::ErrorState error ) { if( error == Playdar::Controller::ErrorState( 1 ) ) emit remove(); } } diff --git a/src/core-impl/collections/playdarcollection/amarok_collection-playdarcollection.desktop b/src/core-impl/collections/playdarcollection/amarok_collection-playdarcollection.desktop index e4034a0dcd..bb40106f16 100644 --- a/src/core-impl/collections/playdarcollection/amarok_collection-playdarcollection.desktop +++ b/src/core-impl/collections/playdarcollection/amarok_collection-playdarcollection.desktop @@ -1,109 +1,109 @@ [Desktop Entry] Type=Service Icon=network-workgroup Name=Playdar Collection Name[bg]=Колекция Playdar Name[bs]=Playdar kolekcija Name[ca]=Col·lecció del Playdar Name[ca@valencia]=Col·lecció del Playdar Name[cs]=Sbírka Playdar Name[da]=Playdar-samling Name[de]=Playdar-Sammlung Name[el]=Συλλογή Playdar Name[en_GB]=Playdar Collection Name[es]=Colección de Playdar Name[et]=Playdari kogu Name[eu]=Playdar bilduma Name[fi]=Playdar-kokoelma Name[fr]=Collection « Playdar » Name[ga]=Bailiúchán Playdar Name[gl]=Colección de Playdar Name[hu]=Playdar gyűjtemény Name[id]=Koleksi Playdar Name[it]=Collezione Playdar Name[ja]=Playdar コレクション Name[km]=សម្រាំង Playdar Name[lt]=Playdar fonoteka Name[lv]=Playdar kolekcija Name[nb]=Playdar-samling Name[nds]=Playdar-Sammeln Name[nl]=Playdar-collectie Name[pl]=Zbiór Playdar Name[pt]=Colecção do Playdar Name[pt_BR]=Coleção do Playdar Name[ro]=Colecție Playdar Name[ru]=Коллекция Playdar Name[sk]=Kolekcia Playdar Name[sl]=Zbirka Playdar Name[sr]=Збирка Плејдара Name[sr@ijekavian]=Збирка Плејдара Name[sr@ijekavianlatin]=Zbirka Playdara Name[sr@latin]=Zbirka Playdara Name[sv]=Playdar-samling Name[tr]=Playdar Koleksiyonu Name[uk]=Збірка Playdar Name[x-test]=xxPlaydar Collectionxx Name[zh_CN]=Playdar 收藏 Name[zh_TW]=Playdar 收藏 Comment=Music that Playdar can find Comment[bg]=Музика откривана с Playdar Comment[bs]=Muzika koju Playdar može pronaći Comment[ca]=Música que el Playdar pot trobar Comment[ca@valencia]=Música que el Playdar pot trobar Comment[cs]=Hudba, kterou může Playdar najít Comment[da]=Musik som Playdar kan finde Comment[de]=Von Playdar auffindbare Musik Comment[el]=Μουσική την οποία το Playdar μπορεί να βρει Comment[en_GB]=Music that Playdar can find Comment[es]=Música que puede encontrar Playdar Comment[et]=Muusika, mida Playdar suudab leida Comment[eu]=Playdar-ek aurki dezakeen musika Comment[fi]=Musiikki, jonka Playdar saa löytää Comment[fr]=Musique que Playdar peut trouver Comment[ga]=Ceol is féidir le Playdar aimsiú Comment[gl]=Música que pode atopar Playdar Comment[hu]=A Playdar által található zenék Comment[id]=Musik Playdar itu dapat dicari Comment[it]=Musica che Playdar può trovare Comment[ja]=Playdar が見つけることのできる音楽 Comment[km]=តន្ត្រី​ដែល​ Playdar អាច​រក​ឃើញ Comment[lt]=Muziką, kurią gali rasti Playdar Comment[lv]=Mūzika, ko atrod Playdar Comment[nb]=Musikk som Playdar kan finne Comment[nds]=Musik, de sik mit Playdar finnen lett Comment[nl]=Muziek die Playdar kan vinden Comment[pl]=Muzyka, której Playdar nie może znaleźć Comment[pt]=Música que o Playdar consegue encontrar Comment[pt_BR]=Música que o Playdar pode encontrar Comment[ro]=Muzică ce poate fi găsită de Playdar Comment[ru]=Модуль коллекции Playdar для Amarok Comment[sk]=Hudba, ktorú môže nájsť Playdar Comment[sl]=Glasba, ki jo lahko najde Playdar Comment[sr]=Музика коју Плејдар проналази Comment[sr@ijekavian]=Музика коју Плејдар проналази Comment[sr@ijekavianlatin]=Muzika koju Playdar pronalazi Comment[sr@latin]=Muzika koju Playdar pronalazi Comment[sv]=Musik som Playdar kan hitta Comment[tr]=Playdar'ın bulabileceği müzik Comment[uk]=Музика, яку може знайти Playdar Comment[x-test]=xxMusic that Playdar can findxx Comment[zh_CN]=Playdar 可找到的音乐 Comment[zh_TW]=Playdar 可以找到的音樂 -ServiceTypes=Amarok/Plugin-disabled +ServiceTypes=Amarok/Plugin X-KDE-Amarok-authors=Andrew Coder X-KDE-Amarok-email=andrew.coder@gmail.com X-KDE-Amarok-framework-version=73 X-KDE-Amarok-name=playdar-collection X-KDE-Amarok-rank=100 X-KDE-Amarok-version=1 X-KDE-PluginInfo-Author=Andrew Coder X-KDE-PluginInfo-Email=andrew.coder@gmail.com X-KDE-PluginInfo-Version=1.0 X-KDE-PluginInfo-Category=Collection X-KDE-PluginInfo-License=GPL X-KDE-PluginInfo-EnabledByDefault=false X-KDE-PluginInfo-Name=amarok_collection-playdarcollection X-KDE-Library=amarok_collection-playdarcollection diff --git a/src/core-impl/collections/playdarcollection/support/Controller.cpp b/src/core-impl/collections/playdarcollection/support/Controller.cpp index d111c1bfbb..6910845dcb 100644 --- a/src/core-impl/collections/playdarcollection/support/Controller.cpp +++ b/src/core-impl/collections/playdarcollection/support/Controller.cpp @@ -1,210 +1,219 @@ /**************************************************************************************** * Copyright (c) 2010 Andrew Coder * * * * 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, see . * ****************************************************************************************/ #define DEBUG_PREFIX "Playdar::Controller" #include "Controller.h" #include "Query.h" #include "core/support/Debug.h" -#include - -#include - +#include +#include +#include #include #include #include #include #include #include +#include + + namespace Playdar { Controller::Controller( bool queriesShouldWaitForSolutions ) : m_errorState( ErrorState( NoError ) ) , m_queriesShouldWaitForSolutions( queriesShouldWaitForSolutions ) { DEBUG_BLOCK } Controller::~Controller() { DEBUG_BLOCK } void Controller::resolve( const QString &artist, const QString &album, const QString &title ) { DEBUG_BLOCK debug() << "Querying playdar for artist name = " << artist << ", album name = " << album << ", and track title = " << title; const QString baseUrl( "http://localhost:60210/api/?method=resolve" ); QUrl resolveUrl( baseUrl ); QUrlQuery query( resolveUrl ); query.addQueryItem( QString( "artist" ), artist ); query.addQueryItem( QString( "album" ), album ); query.addQueryItem( QString( "track" ), title ); resolveUrl.setQuery( query ); debug() << "Starting storedGetJob for " << resolveUrl.url(); KJob* resolveJob = KIO::storedGet( resolveUrl, KIO::Reload, KIO::HideProgressInfo ); connect( resolveJob, &KJob::result, this, &Controller::processQuery ); } void Controller::getResults( Query* query ) { DEBUG_BLOCK const QString baseUrl( "http://localhost:60210/api/?method=get_results" ); QUrl getResultsUrl( baseUrl ); QUrlQuery q( getResultsUrl ); q.addQueryItem( QString( "qid" ), query->qid() ); getResultsUrl.setQuery( q ); KJob* getResultsJob = KIO::storedGet( getResultsUrl, KIO::Reload, KIO::HideProgressInfo ); connect( getResultsJob, &KJob::result, query, &Query::receiveResults ); } void Controller::getResultsLongPoll( Query* query ) { DEBUG_BLOCK const QString baseUrl( "http://localhost:60210/api/?method=get_results_long" ); QUrl getResultsUrl( baseUrl ); QUrlQuery q( getResultsUrl ); q.addQueryItem( QString( "qid" ), query->qid() ); getResultsUrl.setQuery( q ); KJob* getResultsJob = KIO::storedGet( getResultsUrl, KIO::Reload, KIO::HideProgressInfo ); connect( getResultsJob, &KJob::result, query, &Query::receiveResults ); } QUrl Controller::urlForSid( const QString &sid ) const { DEBUG_BLOCK const QString baseUrl( "http://localhost:60210/sid/" ); QUrl playableUrl( baseUrl ); playableUrl = playableUrl.adjusted(QUrl::StripTrailingSlash); playableUrl.setPath(playableUrl.path() + '/' + ( sid )); return playableUrl; } void Controller::status() { // DEBUG_BLOCK const QString baseUrl( "http://localhost:60210/api/?method=stat" ); QUrl statusUrl( baseUrl ); KJob* statusJob = KIO::storedGet( statusUrl, KIO::Reload, KIO::HideProgressInfo ); connect( statusJob, &KJob::result, this, &Controller::processStatus ); } void Controller::processStatus( KJob *statusJob ) { if( statusJob->error() != 0 ) { // debug() << "Error getting status from Playdar"; emit playdarError( Playdar::Controller::ErrorState( ExternalError ) ); return; } debug() << "Processing received JSON data..."; KIO::StoredTransferJob* storedStatusJob = static_cast( statusJob ); - QVariant parsedStatusVariant; - - QJson::Parser parser; - bool ok; - parsedStatusVariant = parser.parse( storedStatusJob->data(),&ok ); - if ( !ok ) + QJsonParseError err; + auto doc = QJsonDocument::fromJson( storedStatusJob->data(), &err ); + + if ( err.error != QJsonParseError::NoError ) + debug() << "Error parsing JSON Data:" << err.errorString(); + + if( !doc.isObject() ) { - debug() << "Error parsing JSON Data"; + debug() << "Parsed Json data is not an object"; + return; } - QVariantMap parsedStatus = parsedStatusVariant.toMap(); + + auto object = doc.object(); - if( !parsedStatus.contains("name") ) + if( !object.contains("name") ) { debug() << "Expected a service name from Playdar, received none"; emit playdarError( Playdar::Controller::ErrorState( MissingServiceName ) ); return; } - if( parsedStatus.value("name") != QString( "playdar" ) ) + if( object.value("name").toString() != QStringLiteral( "playdar" ) ) { debug() << "Expected Playdar, got response from some other service"; emit playdarError( Playdar::Controller::ErrorState( WrongServiceName ) ); return; } debug() << "All good! Emitting playdarReady()"; emit playdarReady(); } void Controller::processQuery( KJob *queryJob ) { DEBUG_BLOCK if( queryJob->error() != 0 ) { debug() << "Error getting qid from Playdar"; emit playdarError( Playdar::Controller::ErrorState( ExternalError ) ); return; } debug() << "Processing received JSON data..."; KIO::StoredTransferJob* storedQueryJob = static_cast( queryJob ); - QVariant parsedQueryVariant; - QJson::Parser parser; - bool ok; - parsedQueryVariant = parser.parse( storedQueryJob->data(),&ok ); - if ( !ok ) + QJsonParseError err; + auto doc = QJsonDocument::fromJson( storedQueryJob->data(), &err ); + + if ( err.error != QJsonParseError::NoError ) + debug() << "Error parsing JSON Data:" << err.errorString(); + + if( !doc.isObject() ) { - debug() << "Error parsing JSON Data"; + debug() << "Parsed Json data is not an object"; + return; } - - QVariantMap parsedQuery = parsedQueryVariant.toMap(); - if( !parsedQuery.contains( "qid" ) ) + + auto object = doc.object(); + + if( !object.contains( "qid" ) ) { debug() << "Expected qid in Playdar's response, but didn't get it"; emit playdarError( Playdar::Controller::ErrorState( MissingQid ) ); return; } - Query* query = new Query( parsedQuery.value( "qid" ).toString(), this, m_queriesShouldWaitForSolutions ); + Query* query = new Query( object.value( "qid" ).toString(), this, m_queriesShouldWaitForSolutions ); debug() << "All good! Emitting queryReady( Playdar::Query* )..."; emit queryReady( query ); connect( query, &Query::playdarError, this, &Controller::playdarError ); } } diff --git a/src/core-impl/collections/playdarcollection/support/Query.cpp b/src/core-impl/collections/playdarcollection/support/Query.cpp index e024fff93c..599574f9f2 100644 --- a/src/core-impl/collections/playdarcollection/support/Query.cpp +++ b/src/core-impl/collections/playdarcollection/support/Query.cpp @@ -1,219 +1,226 @@ /**************************************************************************************** * Copyright (c) 2010 Andrew Coder * * * 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, see . * ****************************************************************************************/ #include "Query.h" #include "Controller.h" #include "core/meta/Meta.h" #include "../PlaydarMeta.h" #include "core/support/Debug.h" -#include - -#include -#include - +#include +#include +#include +#include +#include #include +#include #include -#include #include +#include + + namespace Playdar { Query::Query( const QString &qid, Playdar::Controller* controller, bool waitForSolution ) : m_controller( controller ) , m_waitForSolution( waitForSolution ) , m_qid( qid ) , m_artist( QString( "" ) ) , m_album( QString( "" ) ) , m_title( QString( "" ) ) , m_solved( false ) , m_receivedFirstResults( false ) , m_trackList( ) { DEBUG_BLOCK if( m_waitForSolution ) { m_receivedFirstResults = true; m_controller->getResultsLongPoll( this ); } else m_controller->getResults( this ); } Query::~Query() { DEBUG_BLOCK } QString Query::qid() const { DEBUG_BLOCK return m_qid; } QString Query::artist() const { DEBUG_BLOCK return m_artist; } QString Query::album() const { DEBUG_BLOCK return m_album; } QString Query::title() const { DEBUG_BLOCK return m_title; } bool Query::isSolved() const { DEBUG_BLOCK return m_solved; } Meta::PlaydarTrackList Query::getTrackList() const { DEBUG_BLOCK return m_trackList; } void Query::receiveResults( KJob* resultsJob) { DEBUG_BLOCK if( resultsJob->error() != 0 ) { debug() << "Error getting results from Playdar"; emit playdarError( Playdar::Controller::ErrorState( 1 ) ); return; } debug() << "Processing received JSON data..."; KIO::StoredTransferJob* storedResultsJob = static_cast( resultsJob ); - QJson::Parser parser; - bool ok; - QVariant parsedResultsVariant; - parsedResultsVariant = parser.parse( storedResultsJob->data(),&ok ); - if ( !ok ) + QJsonParseError err; + auto doc = QJsonDocument::fromJson( storedResultsJob->data(), &err ); + + if ( err.error != QJsonParseError::NoError ) + debug() << "Error parsing JSON Data:" << err.errorString(); + + if( !doc.isObject() ) { - debug() << "Error parsing JSON Data"; + debug() << "Parsed Json data is not an object"; + return; } - - QVariantMap parsedResults = parsedResultsVariant.toMap(); - if( !parsedResults.contains( "results" ) ) + + auto object = doc.object(); + + if( !object.contains( "results" ) ) { debug() << "Expecting results in Playdar's response, received none"; emit playdarError( Playdar::Controller::ErrorState( 6 ) ); return; } - if( !parsedResults.contains( "qid" ) ) + if( !object.contains( "qid" ) ) { debug() << "Expected qid in Playdar's response, received none"; emit playdarError( Playdar::Controller::ErrorState( 4 ) ); return; } - if( parsedResults.value( "qid" ) != m_qid ) + if( object.value( "qid" ) != m_qid ) { debug() << "A query received the wrong results from Playdar..."; emit playdarError( Playdar::Controller::ErrorState( 5 ) ); return; } - m_artist = parsedResults.value( "artist" ).toString(); - m_album = parsedResults.value( "album" ).toString(); - m_title = parsedResults.value( "track" ).toString(); + m_artist = object.value( "artist" ).toString(); + m_album = object.value( "album" ).toString(); + m_title = object.value( "track" ).toString(); - foreach( const QVariant &resultVariant, parsedResults.value( "results" ).toList() ) + for( const auto &resultVariant : object.value( "results" ).toArray() ) { - QVariantMap result = resultVariant.toMap(); + auto result = resultVariant.toObject(); Meta::PlaydarTrackPtr aTrack; QUrl resultUrl( m_controller->urlForSid( result.value( "sid" ).toString() ) ); QString trackSid = result.value( "sid" ).toString(); QString trackUrl = resultUrl.url(); QString trackTitle = result.value( "track" ).toString(); QString trackArtist = result.value( "artist" ).toString(); QString trackAlbum = result.value( "album" ).toString(); QString trackType = result.value( "mimetype" ).toString(); QString trackSource = result.value( "source" ).toString(); qint64 trackLengthInSeconds( result.value( "duration" ).toInt() ); aTrack = new Meta::PlaydarTrack ( trackSid, trackUrl, trackTitle, trackArtist, trackAlbum, trackType, result.value( "score" ).toDouble() * 100, ( trackLengthInSeconds * 1000 ), //convert s to ms result.value( "bitrate" ).toInt(), result.value( "size" ).toInt(), trackSource ); if( !m_solved && aTrack->score() >= 1.00 ) { m_solved = true; m_trackList.prepend( aTrack ); emit querySolved( aTrack ); if( m_waitForSolution ) { emit queryDone( this, m_trackList ); return; } } else { m_trackList.append( aTrack ); } emit newTrackAdded( aTrack ); } if( m_receivedFirstResults || m_solved ) { m_receivedFirstResults = true; emit queryDone( this, m_trackList ); } else { m_receivedFirstResults = true; m_controller->getResultsLongPoll( this ); } } }