From 6c8aab319eb644bf5e43d16f33bbff3d13be2989 Mon Sep 17 00:00:00 2001 From: Michael Schwendt Date: Sun, 30 Dec 2018 12:30:10 +0100 Subject: [PATCH] Update to 1.0.2. --- .gitignore | 1 + ampache_browser-1.0-branch-20180408.patch | 731 ---------------------- ampache_browser.spec | 10 +- sources | 2 +- 4 files changed, 7 insertions(+), 737 deletions(-) delete mode 100644 ampache_browser-1.0-branch-20180408.patch diff --git a/.gitignore b/.gitignore index 68ffc26..4bd796c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /ampache_browser-1.0.0.tar.gz +/ampache_browser-1.0.2.tar.gz diff --git a/ampache_browser-1.0-branch-20180408.patch b/ampache_browser-1.0-branch-20180408.patch deleted file mode 100644 index 68014b2..0000000 --- a/ampache_browser-1.0-branch-20180408.patch +++ /dev/null @@ -1,731 +0,0 @@ -diff -Naur ampache_browser-1.0.0-orig/CMakeLists.txt ampache_browser-1.0-branch-20180408/CMakeLists.txt ---- ampache_browser-1.0.0-orig/CMakeLists.txt 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/CMakeLists.txt 2018-04-08 00:28:17.018973008 +0200 -@@ -3,12 +3,12 @@ - # Project: Ampache Browser - # License: GNU GPLv3 - # --# Copyright (C) 2015 - 2017 Róbert Čerňanský -+# Copyright (C) 2015 - 2018 Róbert Čerňanský - - - - cmake_minimum_required(VERSION 3.0) --project(ampache_browser VERSION 1.0.0) -+project(ampache_browser VERSION 1.0.1) - set(VERSION_EXTRA "") - set(soVersion 0) - -diff -Naur ampache_browser-1.0.0-orig/include/internal/data/providers/ampache.h ampache_browser-1.0-branch-20180408/include/internal/data/providers/ampache.h ---- ampache_browser-1.0.0-orig/include/internal/data/providers/ampache.h 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/include/internal/data/providers/ampache.h 2018-04-08 00:28:18.629937302 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -202,7 +202,7 @@ - /** - * @brief Request album arts from the server. - * -- * @note If this method is called before the the ::initialized event it immediately raises ::readyAlbumArts with -+ * @note If this method is called before ::initialized event it immediately raises ::readyAlbumArts with - * zero loaded arts. - * - * @param idsAndUrls Identifiers of the album art images that shall be requested paired with their URLs. IDs are -@@ -290,6 +290,7 @@ - std::vector> createArtists(QXmlStreamReader& xmlStreamReader) const; - void processTracks(QXmlStreamReader& xmlStreamReader, bool error); - std::vector> createTracks(QXmlStreamReader& xmlStreamReader) const; -+ void IfNoPendingClearFinishedAlbumArtsAndRaiseReady(); - std::string assembleUrlBase() const; - }; - -diff -Naur ampache_browser-1.0.0-orig/include/internal/data/repositories/repository.h ampache_browser-1.0-branch-20180408/include/internal/data/repositories/repository.h ---- ampache_browser-1.0.0-orig/include/internal/data/repositories/repository.h 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/include/internal/data/repositories/repository.h 2018-04-08 00:28:18.924930764 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -588,16 +588,27 @@ - offset++; - } - -- auto offsetAndLimit = std::pair{myLoadOffset, data.size()}; -- if (data.size() != static_cast(myLimit)) { -+ // if the server returns less entries than requested, we assume the missing ones are lost (theoretically they -+ // could be deleted sooner than we were able to load them); in that case we store the number of lost entries and -+ // inform that total number of entries has changed (SMELL: we still report the original total -+ // number of entries in maxCount() though); however if happens that the server returns more entries than requested, -+ // we assume that the server ignores 'limit' in the load request and work with returned entries as if they were -+ // requested -+ if (data.size() < static_cast(myLimit)) { - myNumberOfUnavailableEntries += myLimit - data.size(); - dataSizeChanged(); -+ } else if (data.size() > static_cast(myLimit)) { -+ infrastructure::LOG_WARN( -+ "Server does not respect 'limit' parameter. Performance during loading may be degraded."); - } - - myUnfilteredFilter->processUpdatedSourceData(myLoadOffset, data.size()); - if (isFiltered()) { - myFilter->processUpdatedSourceData(myLoadOffset, data.size()); - } -+ -+ auto offsetAndLimit = std::pair{myLoadOffset, data.size()}; -+ - myLoadOffset = -1; - myLoadProgress += data.size(); - infrastructure::LOG_DBG("Load progress: %d.", myLoadProgress); -diff -Naur ampache_browser-1.0.0-orig/include/internal/infrastructure/logging/logging.h ampache_browser-1.0-branch-20180408/include/internal/infrastructure/logging/logging.h ---- ampache_browser-1.0.0-orig/include/internal/infrastructure/logging/logging.h 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/include/internal/infrastructure/logging/logging.h 2018-04-08 00:28:19.611915537 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -19,7 +19,7 @@ - namespace infrastructure { - - /** -- * @brief Sets the maximal loggin level. -+ * @brief Sets the maximal logging level. - * - * If a log method with lower level than maxLogLevel is called, no message is logged. - * -diff -Naur ampache_browser-1.0.0-orig/NEWS ampache_browser-1.0-branch-20180408/NEWS ---- ampache_browser-1.0.0-orig/NEWS 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/NEWS 2018-04-08 00:28:17.165969750 +0200 -@@ -2,6 +2,25 @@ - ==================================== - - -+Version 1.0.1 [????-??-??] -+-------------------------- -+ -+* Fix issues when Nextcloud's Music app is used as Ampache server. -+ -+ Fix crash if server ignores 'limit' parameter and sends more data than it was requested. -+ -+ Fix crash when server returns empty album art URL for not available album arts. -+ -+ Fix crash when album art URL can not be parsed. -+ -+* Ensure the loading error status message is not overwritten. -+ -+ If error occures during loading an error message is shown in status line. Sometimes happened that this message -+ was later overwritten by "Loaded" message when loading finished. This is now fixed so that the error message always -+ stays displayed after loading has finished. -+ -+ -+ - Version 1.0.0 [2017-07-26] - -------------------------- - -diff -Naur ampache_browser-1.0.0-orig/src/application/data_loader.cc ampache_browser-1.0-branch-20180408/src/application/data_loader.cc ---- ampache_browser-1.0.0-orig/src/application/data_loader.cc 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/application/data_loader.cc 2018-04-08 00:28:20.492896011 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -241,6 +241,10 @@ - - - void DataLoader::fireFinished(LoadingResult loadingResult) { -+ if (myState == Idle) { -+ return; -+ } -+ - LOG_INF("Data loader finished with result %d.", loadingResult); - myState = Idle; - finished(loadingResult); -diff -Naur ampache_browser-1.0.0-orig/src/application/models/album_model.cc ampache_browser-1.0-branch-20180408/src/application/models/album_model.cc ---- ampache_browser-1.0.0-orig/src/application/models/album_model.cc 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/application/models/album_model.cc 2018-04-08 00:28:20.687891689 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -125,9 +125,9 @@ - - - --void AlbumModel::onLoaded(pair) { -- auto finishedRequestGroup = myAlbumRequests->setFinished(); -- dataChanged(createIndex(finishedRequestGroup.getLower(), 0), createIndex(finishedRequestGroup.getUpper(), 0)); -+void AlbumModel::onLoaded(pair offsetAndLimit) { -+ myAlbumRequests->setFinished(offsetAndLimit.first, offsetAndLimit.second); -+ dataChanged(createIndex(offsetAndLimit.first, 0), createIndex(offsetAndLimit.first + offsetAndLimit.second - 1, 0)); - } - - -@@ -143,13 +143,14 @@ - - - void AlbumModel::onArtsLoaded(pair offsetAndCount) { -- auto finishedRequestGroup = myArtRequests->setFinished(); -+ myArtRequests->setFinished(offsetAndCount.first, offsetAndCount.second); - if (myIsInUnfilteredArtsLoadMode) { - return; - } - - if (offsetAndCount.second != 0) { -- dataChanged(createIndex(finishedRequestGroup.getLower(), 0), createIndex(finishedRequestGroup.getUpper(), 0)); -+ dataChanged(createIndex(offsetAndCount.first, 0), -+ createIndex(offsetAndCount.first + offsetAndCount.second - 1, 0)); - } - - if (!myArtRequests->isInProgress()) { -diff -Naur ampache_browser-1.0.0-orig/src/application/models/artist_model.cc ampache_browser-1.0-branch-20180408/src/application/models/artist_model.cc ---- ampache_browser-1.0.0-orig/src/application/models/artist_model.cc 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/application/models/artist_model.cc 2018-04-08 00:28:20.736890603 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -90,9 +90,9 @@ - - - --void ArtistModel::onLoaded(pair) { -- auto finishedRequestGroup = myRequests->setFinished(); -- dataChanged(createIndex(finishedRequestGroup.getLower(), 0), createIndex(finishedRequestGroup.getUpper(), 0)); -+void ArtistModel::onLoaded(pair offsetAndLimit) { -+ myRequests->setFinished(offsetAndLimit.first, offsetAndLimit.second); -+ dataChanged(createIndex(offsetAndLimit.first, 0), createIndex(offsetAndLimit.first + offsetAndLimit.second - 1, 0)); - } - - -diff -Naur ampache_browser-1.0.0-orig/src/application/models/request_groups.cc ampache_browser-1.0-branch-20180408/src/application/models/request_groups.cc ---- ampache_browser-1.0.0-orig/src/application/models/request_groups.cc 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/application/models/request_groups.cc 2018-04-08 00:28:20.883887345 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -27,20 +27,15 @@ - - - --void RequestGroups::cutAndPlaceOnTop(RequestGroup requestGroup) { -- auto intersectingGroupIdxs = findIntersectingGroupIdxs(requestGroup); -- for (auto idx = intersectingGroupIdxs.size(); idx-- > 0;) { -- auto intersectingGroupIdx = intersectingGroupIdxs[idx]; -- auto intersectingGroup = myRequestGroups[intersectingGroupIdx]; -- pair remainderGroups = intersectingGroup.substract(requestGroup); -- myRequestGroups.erase(myRequestGroups.begin() + intersectingGroupIdx); -- if (!remainderGroups.second.isEmpty()) { -- myRequestGroups.insert(myRequestGroups.begin() + intersectingGroupIdx, remainderGroups.second); -- } -- if (!remainderGroups.first.isEmpty()) { -- myRequestGroups.insert(myRequestGroups.begin() + intersectingGroupIdx, remainderGroups.first); -- } -- } -+void RequestGroups::cut(RequestGroup requestGroup) { -+ cutRequestGroup(requestGroup); -+ chop(); -+} -+ -+ -+ -+void RequestGroups::moveOnTop(RequestGroup requestGroup) { -+ cutRequestGroup(requestGroup); - myRequestGroups.push_back(requestGroup); - chop(); - } -@@ -89,6 +84,25 @@ - } - - -+ -+void RequestGroups::cutRequestGroup(RequestGroup requestGroup) { -+ auto intersectingGroupIdxs = findIntersectingGroupIdxs(requestGroup); -+ for (auto idx = intersectingGroupIdxs.size(); idx-- > 0;) { -+ auto intersectingGroupIdx = intersectingGroupIdxs[idx]; -+ auto intersectingGroup = myRequestGroups[intersectingGroupIdx]; -+ pair remainderGroups = intersectingGroup.substract(requestGroup); -+ -+ myRequestGroups.erase(myRequestGroups.begin() + intersectingGroupIdx); -+ if (!remainderGroups.second.isEmpty()) { -+ myRequestGroups.insert(myRequestGroups.begin() + intersectingGroupIdx, remainderGroups.second); -+ } -+ if (!remainderGroups.first.isEmpty()) { -+ myRequestGroups.insert(myRequestGroups.begin() + intersectingGroupIdx, remainderGroups.first); -+ } -+ } -+} -+ -+ - - void RequestGroups::chop() { - if (myGranularity == 0) { -diff -Naur ampache_browser-1.0.0-orig/src/application/models/request_groups.h ampache_browser-1.0-branch-20180408/src/application/models/request_groups.h ---- ampache_browser-1.0.0-orig/src/application/models/request_groups.h 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/application/models/request_groups.h 2018-04-08 00:28:20.933886236 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -44,18 +44,30 @@ - */ - bool isEmpty() const; - -+ - /** -- * @brief Cuts @p requestGroup from the set and places it on top. -+ * @brief Cuts @p requestGroup from the set. - * -- * The operation modifies/removes affected groups as needed. For example of @p requestGroup is big, spreading -- * over (intersecting with) several groups in the set, those are removed and groups intersecting on bounds are -- * shrinked accordingly. -+ * The operation modifies/removes affected groups as needed. For example if @p requestGroup is big, spreading -+ * over (intersecting with) several groups in the set, inner intersecting groups are removed and groups -+ * intersecting on bounds are shrinked accordingly. - * -- * The entire set is then modified so that no group is bigger than the set granularity. -+ * @note The entire set is then modified so that no group is bigger than the set granularity. -+ * -+ * @param requestGroup Group that shall be cut. -+ */ -+ void cut(RequestGroup requestGroup); -+ -+ /** -+ * @brief Cuts @p requestGroup from the set and places it on top. -+ * -+ * @note The entire set is then modified so that no group is bigger than the set granularity. - * - * @param requestGroup The group that shall be cut and moved. -+ * -+ * @sa cut() - */ -- void cutAndPlaceOnTop(RequestGroup requestGroup); -+ void moveOnTop(RequestGroup requestGroup); - - /** - * @brief Make grup determined by @p offset bigger by one. -@@ -88,6 +100,7 @@ - // stored groups - std::vector myRequestGroups; - -+ void cutRequestGroup(RequestGroup requestGroup); - void chop(); - void appendOnTop(std::vector& groups, RequestGroup groupToPlace); - int findOwningGroupIdx(int offset) const; -diff -Naur ampache_browser-1.0.0-orig/src/application/models/requests.cc ampache_browser-1.0-branch-20180408/src/application/models/requests.cc ---- ampache_browser-1.0.0-orig/src/application/models/requests.cc 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/application/models/requests.cc 2018-04-08 00:28:20.983885128 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -38,9 +38,9 @@ - } - - if (offset < myLastEnqueuedOffset) { -- myRequestGroups->cutAndPlaceOnTop(RequestGroup{offset, offset}); -+ myRequestGroups->moveOnTop(RequestGroup{offset, offset}); - } else if (offset > myLastEnqueuedOffset + 1) { -- myRequestGroups->cutAndPlaceOnTop(RequestGroup{offset, offset}); -+ myRequestGroups->moveOnTop(RequestGroup{offset, offset}); - } else { - myRequestGroups->extend(offset); - } -@@ -55,10 +55,15 @@ - - - --// SMELL: Not necesary to expose RequestGroup. Return just pair and Requests will be the only --// "interface" class to request handling. Same for readyToExecute event. --RequestGroup Requests::setFinished() { -- auto finishedRequestGroup = myCurrentRequestGroup; -+void Requests::setFinished(int offset, int count) { -+ auto finishedRequestGroup = RequestGroup{offset, offset + count - 1}; -+ -+ // finished requests may be different from what was ready to execution; if there were some requests finished which -+ // were not ready remainderGroups will contain them; they have to be cut from myRequestGroups -+ auto remainderGroups = finishedRequestGroup.substract(myCurrentRequestGroup); -+ myRequestGroups->cut(remainderGroups.first); -+ myRequestGroups->cut(remainderGroups.second); -+ - if (!myRequestGroups->isEmpty()) { - myCurrentRequestGroup = myRequestGroups->pop(); - readyToExecute(myCurrentRequestGroup); -@@ -66,7 +71,6 @@ - myCurrentRequestGroup = RequestGroup{}; - myLastEnqueuedOffset = numeric_limits::max(); - } -- return finishedRequestGroup; - } - - -diff -Naur ampache_browser-1.0.0-orig/src/application/models/requests.h ampache_browser-1.0-branch-20180408/src/application/models/requests.h ---- ampache_browser-1.0.0-orig/src/application/models/requests.h 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/application/models/requests.h 2018-04-08 00:28:21.031884065 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -56,6 +56,8 @@ - - Requests& operator=(const Requests& other) = delete; - -+ // SMELL: Not necesary to expose RequestGroup. Use just pair<> as parameter and Requests will be the only -+ // "interface" class to request handling. Same for readyToExecute event. - /** - * @brief A group of requests is ready to be executed. - * -@@ -82,11 +84,15 @@ - /** - * @brief Inform the instance that the operation started upon ::readyToExecute event has finished. - * -- * @return Group of requests for which the operation was previously ready to be executed. -+ * Ready to execute requests which are not reported as finished will be set as finished (will not be -+ * executed again). Finished requests which were not ready to execute will also be set as finished. -+ * -+ * @param offset The number of first finished request (may be different from what was originally requested). -+ * @param count The count of finished requests (may be different from what was originally requested). - * - * @sa ::readyToExecute - */ -- RequestGroup setFinished(); -+ void setFinished(int offset, int count); - - /** - * @brief Returns true if some operation is being executed. -diff -Naur ampache_browser-1.0.0-orig/src/application/models/track_model.cc ampache_browser-1.0-branch-20180408/src/application/models/track_model.cc ---- ampache_browser-1.0.0-orig/src/application/models/track_model.cc 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/application/models/track_model.cc 2018-04-08 00:28:21.080882978 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -121,9 +121,9 @@ - - - --void TrackModel::onLoaded(pair) { -- auto finishedRequestGroup = myRequests->setFinished(); -- dataChanged(createIndex(finishedRequestGroup.getLower(), 0), createIndex(finishedRequestGroup.getUpper(), 0)); -+void TrackModel::onLoaded(pair offsetAndLimit) { -+ myRequests->setFinished(offsetAndLimit.first, offsetAndLimit.second); -+ dataChanged(createIndex(offsetAndLimit.first, 0), createIndex(offsetAndLimit.first + offsetAndLimit.second - 1, 0)); - } - - -diff -Naur ampache_browser-1.0.0-orig/src/data/indices.cc ampache_browser-1.0-branch-20180408/src/data/indices.cc ---- ampache_browser-1.0.0-orig/src/data/indices.cc 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/data/indices.cc 2018-04-08 00:28:22.065861147 +0200 -@@ -19,8 +19,8 @@ - - void Indices::addArtists(const vector>& artists) { - for (auto& artist: artists) { -- myArtistAlbums[artist.get()] = move(AlbumDataUnorderedSet{}); -- myArtistTracks[artist.get()] = move(TrackDataUnorderedSet{}); -+ myArtistAlbums[artist.get()] = AlbumDataUnorderedSet{}; -+ myArtistTracks[artist.get()] = TrackDataUnorderedSet{}; - } - } - -@@ -28,7 +28,7 @@ - - void Indices::addAlbums(const vector>& albums) { - for (auto& album: albums) { -- myAlbumTracks[album.get()] = move(TrackDataUnorderedSet{}); -+ myAlbumTracks[album.get()] = TrackDataUnorderedSet{}; - } - } - -diff -Naur ampache_browser-1.0.0-orig/src/data/providers/ampache/ampache.cc ampache_browser-1.0-branch-20180408/src/data/providers/ampache/ampache.cc ---- ampache_browser-1.0.0-orig/src/data/providers/ampache/ampache.cc 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/data/providers/ampache/ampache.cc 2018-04-08 00:28:22.212857889 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -125,11 +125,24 @@ - return; - } - -+ // SMELL: size specified on multiple places -+ QPixmap notAvailablePixmap{100, 100}; -+ notAvailablePixmap.fill(QColor(230, 225, 220)); -+ - LOG_DBG("Getting %d album arts.", idsAndUrls.size()); - for (auto& idAndUrl: idsAndUrls) { -- myPendingAlbumArts.insert(idAndUrl.first); -- myNetworkRequestFn(idAndUrl.second, myAlbumArtsNetworkRequestCb); -+ if (idAndUrl.second.empty()) { -+ // SMELL: If the server did not provide any Art URL then it would be better if client (frontend/model) -+ // created the replacement Art (with the "Not Available" image of its choice). Currently, Ampache (3.8.3) -+ // provides URLs for not available Arts as well; Nextcloud's Music app (0.5.6) sends empty URLs for -+ // not available Arts. -+ myFinishedAlbumArts.emplace(idAndUrl.first, notAvailablePixmap); -+ } else { -+ myPendingAlbumArts.insert(idAndUrl.first); -+ myNetworkRequestFn(idAndUrl.second, myAlbumArtsNetworkRequestCb); -+ } - } -+ IfNoPendingClearFinishedAlbumArtsAndRaiseReady(); - } - - -@@ -168,8 +181,20 @@ - void Ampache::onAlbumArtsNetworkRequestFinished(const string& artUrl, const char* content, int contentSize) { - LOG_DBG("Album art request has returned with network content of length %d.", contentSize); - -- auto scaleAlbumArtRunnable = new ScaleAlbumArtRunnable(AmpacheUrl{artUrl}.parseIdValue(), -- QByteArray{content, contentSize}); -+ // SMELL: Format of Album Art URL is not server's public API. Entire url should be the ID (mapped to album ID). -+ // Ampache (3.8.3) passes the album ID in parameter 'id'; Nextcloud's Music app (0.5.6) in parameter 'filter' -+ auto id = AmpacheUrl{artUrl}.parseIdValue(); -+ id = id.empty() ? AmpacheUrl{artUrl}.parseFilterValue() : id; -+ -+ // give up if we could not parse ID -+ if (id.empty()) { -+ myFinishedAlbumArts.clear(); // returning empty finished album arts list means error -+ myPendingAlbumArts.clear(); -+ IfNoPendingClearFinishedAlbumArtsAndRaiseReady(); -+ return; -+ } -+ -+ auto scaleAlbumArtRunnable = new ScaleAlbumArtRunnable(id, QByteArray{content, contentSize}); - scaleAlbumArtRunnable->setAutoDelete(false); - connect(scaleAlbumArtRunnable, SIGNAL(finished(ScaleAlbumArtRunnable*)), this, - SLOT(onScaleAlbumArtRunnableFinished(ScaleAlbumArtRunnable*))); -@@ -190,12 +215,7 @@ - myFinishedAlbumArts.emplace(albumId, art); - myPendingAlbumArts.erase(albumId); - -- if (myPendingAlbumArts.empty()) { -- auto finishedAlbumArts = myFinishedAlbumArts; -- myFinishedAlbumArts.clear(); -- -- readyAlbumArts(finishedAlbumArts); -- } -+ IfNoPendingClearFinishedAlbumArtsAndRaiseReady(); - } - - -@@ -387,16 +407,16 @@ - if (xmlElement == "album") { - QXmlStreamAttributes attributes = xmlStreamReader.attributes(); - if (attributes.hasAttribute("id")) { -- id = attributes.value("id").toString().toStdString(); -+ id = attributes.value("id").toString().trimmed().toStdString(); - } - } else if (xmlElement == "artist") { - QXmlStreamAttributes attributes = xmlStreamReader.attributes(); - if (attributes.hasAttribute("id")) { -- artistId = attributes.value("id").toString().toStdString(); -+ artistId = attributes.value("id").toString().trimmed().toStdString(); - } - } - else { -- auto value = xmlStreamReader.readElementText().toStdString(); -+ auto value = xmlStreamReader.readElementText().trimmed().toStdString(); - - if (xmlElement == "name") { - albumName = value; -@@ -419,6 +439,7 @@ - } catch (const invalid_argument& ex) {} - catch (const out_of_range& ex) {} - } else if (xmlElement == "art") { -+ // TODO: Sanitize URL. - artUrl = value; - } - } -@@ -478,11 +499,11 @@ - if (xmlElement == "artist") { - QXmlStreamAttributes attributes = xmlStreamReader.attributes(); - if (attributes.hasAttribute("id")) { -- id = attributes.value("id").toString().toStdString(); -+ id = attributes.value("id").toString().trimmed().toStdString(); - } - } - else { -- auto value = xmlStreamReader.readElementText().toStdString(); -+ auto value = xmlStreamReader.readElementText().trimmed().toStdString(); - - if (xmlElement == "name") { - artistName = value; -@@ -558,21 +579,21 @@ - if (xmlElement == "song") { - QXmlStreamAttributes attributes = xmlStreamReader.attributes(); - if (attributes.hasAttribute("id")) { -- id = attributes.value("id").toString().toStdString(); -+ id = attributes.value("id").toString().trimmed().toStdString(); - } - } else if (xmlElement == "artist") { - QXmlStreamAttributes attributes = xmlStreamReader.attributes(); - if (attributes.hasAttribute("id")) { -- artistId = attributes.value("id").toString().toStdString(); -+ artistId = attributes.value("id").toString().trimmed().toStdString(); - } - } else if (xmlElement == "album") { - QXmlStreamAttributes attributes = xmlStreamReader.attributes(); - if (attributes.hasAttribute("id")) { -- albumId = attributes.value("id").toString().toStdString(); -+ albumId = attributes.value("id").toString().trimmed().toStdString(); - } - } - else { -- auto value = xmlStreamReader.readElementText().toStdString(); -+ auto value = xmlStreamReader.readElementText().trimmed().toStdString(); - - if (xmlElement == "title") { - title = value; -@@ -583,6 +604,7 @@ - } catch (const invalid_argument& ex) {} - catch (const out_of_range& ex) {} - } else if (xmlElement == "url") { -+ // TODO: Sanitize URL. - url = value; - } - } -@@ -596,6 +618,17 @@ - } - - -+ -+void Ampache::IfNoPendingClearFinishedAlbumArtsAndRaiseReady() { -+ if (myPendingAlbumArts.empty()) { -+ auto finishedAlbumArts = myFinishedAlbumArts; -+ myFinishedAlbumArts.clear(); -+ -+ readyAlbumArts(finishedAlbumArts); -+ } -+} -+ -+ - - string Ampache::assembleUrlBase() const { - return myConnectionInfo.getServerUrl() + "/server/xml.server.php?action="; -diff -Naur ampache_browser-1.0.0-orig/src/data/providers/ampache/ampache_url.cc ampache_browser-1.0-branch-20180408/src/data/providers/ampache/ampache_url.cc ---- ampache_browser-1.0.0-orig/src/data/providers/ampache/ampache_url.cc 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/data/providers/ampache/ampache_url.cc 2018-04-08 00:28:22.261856803 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -29,6 +29,12 @@ - - - -+string AmpacheUrl::parseFilterValue() const { -+ return parseValue(PARAM_FILTER); -+} -+ -+ -+ - string AmpacheUrl::parseActionValue() const { - return parseValue(PARAM_ACTION); - } -@@ -92,6 +98,7 @@ - const string AmpacheUrl::PARAM_SSID = "ssid"; - const string AmpacheUrl::PARAM_AUTH = "auth"; - const string AmpacheUrl::PARAM_ID = "id"; -+const string AmpacheUrl::PARAM_FILTER = "filter"; - const string AmpacheUrl::PARAM_ACTION = "action"; - - } -diff -Naur ampache_browser-1.0.0-orig/src/data/providers/ampache/ampache_url.h ampache_browser-1.0-branch-20180408/src/data/providers/ampache/ampache_url.h ---- ampache_browser-1.0.0-orig/src/data/providers/ampache/ampache_url.h 2017-07-26 17:44:25.000000001 +0200 -+++ ampache_browser-1.0-branch-20180408/src/data/providers/ampache/ampache_url.h 2018-04-08 00:28:22.310855717 +0200 -@@ -3,7 +3,7 @@ - // Project: Ampache Browser - // License: GNU GPLv3 - // --// Copyright (C) 2015 - 2016 Róbert Čerňanský -+// Copyright (C) 2015 - 2018 Róbert Čerňanský - - - -@@ -39,6 +39,14 @@ - */ - std::string parseIdValue() const; - -+ -+ /** -+ * @brief Gets value of parameter 'filter'. -+ * -+ * @return std::string -+ */ -+ std::string parseFilterValue() const; -+ - /** - * @brief Gets value of parameter 'action'. - * -@@ -74,6 +82,7 @@ - static const std::string PARAM_SSID; - static const std::string PARAM_AUTH; - static const std::string PARAM_ID; -+ static const std::string PARAM_FILTER; - static const std::string PARAM_ACTION; - - // arguments from the constructor diff --git a/ampache_browser.spec b/ampache_browser.spec index db228b5..2531566 100644 --- a/ampache_browser.spec +++ b/ampache_browser.spec @@ -4,8 +4,8 @@ Name: ampache_browser # is likely to break API users due to not finding files any longer. %global vername %{name}_1 -Version: 1.0.0 -Release: 4.20180408%{?dist} +Version: 1.0.2 +Release: 1%{?dist} Summary: C++ and Qt based client library for Ampache access License: GPLv3 @@ -13,9 +13,6 @@ URL: http://ampache-browser.org Source0: https://github.com/ampache-browser/ampache_browser/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz # Source0: https://github.com/ampache-browser/ampache_browser/archive/v%{version}/%{name}-%{version}.tar.gz -# https://github.com/ampache-browser/ampache_browser/tree/v1.0 -Patch0: ampache_browser-1.0-branch-20180408.patch - BuildRequires: cmake BuildRequires: gcc-c++ BuildRequires: qt5-devel @@ -65,6 +62,9 @@ find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' %{_libdir}/cmake/%{vername} %changelog +* Sun Dec 30 2018 Michael Schwendt - 1.0.2-1 +- Update to 1.0.2. + * Thu Jul 12 2018 Fedora Release Engineering - 1.0.0-4.20180408 - Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild diff --git a/sources b/sources index 71202c5..d63c212 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (ampache_browser-1.0.0.tar.gz) = 9757052a98134177f185fb8214f64c72f601d27c0b5fc924b5ff0fdaac849e188c03f81b4806e14f97c102b1b74791813272aceed97b3f8a5ecfadc374ea0269 +SHA512 (ampache_browser-1.0.2.tar.gz) = c96008ffa3abc87c9ca8a534e1eb8e8b6aea85c404421f8bd635f1755774673e6f0c956e36e1be642c5f0e1443547c59c2ae9283fb75b0dcefa4c5f9d23e438b