Merge pull request #25 from ultrasonic/use-get-artists

Use getArtists new api implementation call
This commit is contained in:
Yahor Berdnikau 2017-08-16 07:42:51 +02:00 committed by GitHub
commit 6b8d953751
8 changed files with 159 additions and 189 deletions

View File

@ -164,17 +164,18 @@ class SubsonicAPIClientTest {
lastModified `should equal` 1491069027523
ignoredArticles `should equal` "The El La Los Las Le Les"
shortcutList `should equal` listOf(
Artist(889L, "podcasts", null),
Artist(890L, "audiobooks", null)
Artist(id = 889L, name = "podcasts"),
Artist(id = 890L, name = "audiobooks")
)
indexList `should equal` mutableListOf(
Index("A", listOf(
Artist(50L, "Ace Of Base", parseDate("2017-04-02T20:16:29.815Z")),
Artist(379L, "A Perfect Circle", null)
Artist(id = 50L, name = "Ace Of Base",
starred = parseDate("2017-04-02T20:16:29.815Z")),
Artist(id = 379L, name = "A Perfect Circle")
)),
Index("H", listOf(
Artist(299, "Haddaway", null),
Artist(297, "Halestorm", null)
Artist(id = 299, name = "Haddaway"),
Artist(id = 297, name = "Halestorm")
))
)
}
@ -271,6 +272,55 @@ class SubsonicAPIClientTest {
}
}
@Test
fun `Should parse get artists error response`() {
val response = checkErrorCallParsed { client.api.getArtists(null).execute() }
response.indexes `should not be` null
with(response.indexes) {
lastModified `should equal to` 0
ignoredArticles `should equal to` ""
indexList.size `should equal to` 0
shortcutList.size `should equal to` 0
}
}
@Test
fun `Should parse get artists ok reponse`() {
enqueueResponse("get_artists_ok.json")
val response = client.api.getArtists(null).execute()
assertResponseSuccessful(response)
with(response.body().indexes) {
lastModified `should equal to` 0L
ignoredArticles `should equal to` "The El La Los Las Le Les"
shortcutList `should equal` emptyList()
indexList.size `should equal to` 2
indexList `should equal` listOf(
Index(name = "A", artists = listOf(
Artist(id = 362L, name = "AC/DC", coverArt = "ar-362", albumCount = 2),
Artist(id = 254L, name = "Acceptance", coverArt = "ar-254", albumCount = 1)
)),
Index(name = "T", artists = listOf(
Artist(id = 516L, name = "Tangerine Dream", coverArt = "ar-516", albumCount = 1),
Artist(id = 242L, name = "Taproot", coverArt = "ar-242", albumCount = 2)
))
)
}
}
@Test
fun `Should pass param on query for get artists call`() {
enqueueResponse("get_artists_ok.json")
val musicFolderId = 101L
client.api.getArtists(musicFolderId).execute()
val request = mockWebServerRule.mockWebServer.takeRequest()
request.requestLine `should contain` "musicFolderId=$musicFolderId"
}
private fun enqueueResponse(resourceName: String) {
mockWebServerRule.mockWebServer.enqueue(MockResponse()
.setBody(loadJsonResponse(resourceName)))

View File

@ -0,0 +1,43 @@
{
"subsonic-response": {
"status": "ok",
"version": "1.15.0",
"artists": {
"ignoredArticles": "The El La Los Las Le Les",
"index": [
{
"name": "A",
"artist": [
{
"id": "362",
"name": "AC/DC",
"coverArt": "ar-362",
"albumCount": 2
},
{
"id": "254",
"name": "Acceptance",
"coverArt": "ar-254",
"albumCount": 1
}
]
}, {
"name": "T",
"artist": [
{
"id": "516",
"name": "Tangerine Dream",
"coverArt": "ar-516",
"albumCount": 1
},
{
"id": "242",
"name": "Taproot",
"coverArt": "ar-242",
"albumCount": 2
}
]
} ]
}
}
}

View File

@ -1,5 +1,6 @@
package org.moire.ultrasonic.api.subsonic
import org.moire.ultrasonic.api.subsonic.response.GetArtistsResponse
import org.moire.ultrasonic.api.subsonic.response.GetIndexesResponse
import org.moire.ultrasonic.api.subsonic.response.GetMusicDirectoryResponse
import org.moire.ultrasonic.api.subsonic.response.LicenseResponse
@ -30,4 +31,7 @@ interface SubsonicAPIDefinition {
@GET("getMusicDirectory.view")
fun getMusicDirectory(@Query("id") id: Long): Call<GetMusicDirectoryResponse>
@GET("getArtists.view")
fun getArtists(@Query("musicFolderId") musicFolderId: Long?): Call<GetArtistsResponse>
}

View File

@ -4,4 +4,6 @@ import java.util.Calendar
data class Artist(val id: Long = -1,
val name: String = "",
val starred: Calendar?)
val coverArt: String = "",
val albumCount: Int = 0,
val starred: Calendar? = null)

View File

@ -0,0 +1,12 @@
package org.moire.ultrasonic.api.subsonic.response
import com.fasterxml.jackson.annotation.JsonProperty
import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions
import org.moire.ultrasonic.api.subsonic.SubsonicError
import org.moire.ultrasonic.api.subsonic.models.Indexes
class GetArtistsResponse(status: Status,
version: SubsonicAPIVersions,
error: SubsonicError?,
@JsonProperty("artists") val indexes: Indexes = Indexes()) :
SubsonicResponse(status, version, error)

View File

@ -56,6 +56,7 @@ import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.moire.ultrasonic.R;
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient;
import org.moire.ultrasonic.api.subsonic.response.GetArtistsResponse;
import org.moire.ultrasonic.api.subsonic.response.GetIndexesResponse;
import org.moire.ultrasonic.api.subsonic.response.LicenseResponse;
import org.moire.ultrasonic.api.subsonic.response.MusicFoldersResponse;
@ -81,7 +82,6 @@ import org.moire.ultrasonic.service.parser.BookmarkParser;
import org.moire.ultrasonic.service.parser.ChatMessageParser;
import org.moire.ultrasonic.service.parser.ErrorParser;
import org.moire.ultrasonic.service.parser.GenreParser;
import org.moire.ultrasonic.service.parser.IndexesParser;
import org.moire.ultrasonic.service.parser.JukeboxStatusParser;
import org.moire.ultrasonic.service.parser.LyricsParser;
import org.moire.ultrasonic.service.parser.MusicDirectoryParser;
@ -234,6 +234,21 @@ public class RESTMusicService implements MusicService
return musicFolders;
}
private static List<MusicFolder> readCachedMusicFolders(Context context) {
String filename = getCachedMusicFoldersFilename(context);
return FileUtil.deserialize(context, filename);
}
private static void writeCachedMusicFolders(Context context, List<MusicFolder> musicFolders) {
String filename = getCachedMusicFoldersFilename(context);
FileUtil.serialize(context, new ArrayList<>(musicFolders), filename);
}
private static String getCachedMusicFoldersFilename(Context context) {
String s = Util.getRestUrl(context, null);
return String.format(Locale.US, "musicFolders-%d.ser", Math.abs(s.hashCode()));
}
@Override
public Indexes getIndexes(String musicFolderId,
boolean refresh,
@ -269,68 +284,38 @@ public class RESTMusicService implements MusicService
return String.format(Locale.US, "indexes-%d.ser", Math.abs(s.hashCode()));
}
@Override
public Indexes getArtists(boolean refresh, Context context, ProgressListener progressListener) throws Exception
{
checkServerVersion(context, "1.8", "Artists by ID3 tag not supported.");
@Override
public Indexes getArtists(boolean refresh,
Context context,
ProgressListener progressListener) throws Exception {
Indexes cachedArtists = readCachedArtists(context);
if (cachedArtists != null &&
!refresh) {
return cachedArtists;
}
Indexes cachedArtists = readCachedArtists(context);
if (cachedArtists != null && !refresh)
{
return cachedArtists;
}
Response<GetArtistsResponse> response = subsonicAPIClient.getApi().getArtists(null).execute();
checkResponseSuccessful(response);
Reader reader = getReader(context, progressListener, "getArtists", null);
try
{
Indexes indexes = new IndexesParser(context).parse(reader, progressListener);
if (indexes != null)
{
writeCachedArtists(context, indexes);
return indexes;
}
Indexes indexes = APIConverter.toDomainEntity(response.body().getIndexes());
writeCachedArtists(context, indexes);
return indexes;
}
return cachedArtists != null ? cachedArtists : new Indexes(0, null, new ArrayList<org.moire.ultrasonic.domain.Artist>(), new ArrayList<org.moire.ultrasonic.domain.Artist>());
}
finally
{
Util.close(reader);
}
}
private static Indexes readCachedArtists(Context context)
{
String filename = getCachedArtistsFilename(context);
return FileUtil.deserialize(context, filename);
}
private static void writeCachedArtists(Context context, Indexes artists)
{
String filename = getCachedArtistsFilename(context);
FileUtil.serialize(context, artists, filename);
}
private static String getCachedArtistsFilename(Context context)
{
String s = Util.getRestUrl(context, null);
return String.format("indexes-%d.ser", Math.abs(s.hashCode()));
}
private static List<MusicFolder> readCachedMusicFolders(Context context) {
String filename = getCachedMusicFoldersFilename(context);
private static Indexes readCachedArtists(Context context) {
String filename = getCachedArtistsFilename(context);
return FileUtil.deserialize(context, filename);
}
private static void writeCachedMusicFolders(Context context, List<MusicFolder> musicFolders) {
String filename = getCachedMusicFoldersFilename(context);
FileUtil.serialize(context, new ArrayList<>(musicFolders), filename);
private static void writeCachedArtists(Context context, Indexes artists) {
String filename = getCachedArtistsFilename(context);
FileUtil.serialize(context, artists, filename);
}
private static String getCachedMusicFoldersFilename(Context context)
{
String s = Util.getRestUrl(context, null);
return String.format("musicFolders-%d.ser", Math.abs(s.hashCode()));
}
private static String getCachedArtistsFilename(Context context) {
String s = Util.getRestUrl(context, null);
return String.format(Locale.US, "indexes-%d.ser", Math.abs(s.hashCode()));
}
@Override
public void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception

View File

@ -1,126 +0,0 @@
/*
This file is part of Subsonic.
Subsonic 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.
Subsonic 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 Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009 (C) Sindre Mehus
*/
package org.moire.ultrasonic.service.parser;
import android.content.Context;
import android.util.Log;
import org.moire.ultrasonic.R;
import org.moire.ultrasonic.domain.Artist;
import org.moire.ultrasonic.domain.Indexes;
import org.moire.ultrasonic.util.ProgressListener;
import org.xmlpull.v1.XmlPullParser;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
/**
* @author Sindre Mehus
*/
public class IndexesParser extends AbstractParser
{
private static final String TAG = IndexesParser.class.getSimpleName();
private Context context;
public IndexesParser(Context context)
{
super(context);
this.context = context;
}
public Indexes parse(Reader reader, ProgressListener progressListener) throws Exception
{
long t0 = System.currentTimeMillis();
updateProgress(progressListener, R.string.parser_reading);
init(reader);
List<Artist> artists = new ArrayList<Artist>();
List<Artist> shortcuts = new ArrayList<Artist>();
Long lastModified = null;
String ignoredArticles = null;
int eventType;
String index = "#";
boolean changed = false;
do
{
eventType = nextParseEvent();
if (eventType == XmlPullParser.START_TAG)
{
String name = getElementName();
if ("indexes".equals(name) || "artists".equals(name))
{
changed = true;
lastModified = getLong("lastModified");
ignoredArticles = get("ignoredArticles");
}
else if ("index".equals(name))
{
index = get("name");
}
else if ("artist".equals(name))
{
Artist artist = new Artist();
artist.setId(get("id"));
artist.setName(get("name"));
artist.setCoverArt(get("coverArt"));
artist.setAlbumCount(getLong("albumCount"));
artist.setIndex(index);
artists.add(artist);
if (artists.size() % 10 == 0)
{
String msg = this.context.getResources().getString(R.string.parser_artist_count, artists.size());
updateProgress(progressListener, msg);
}
}
else if ("shortcut".equals(name))
{
Artist shortcut = new Artist();
shortcut.setId(get("id"));
shortcut.setName(get("name"));
shortcut.setIndex("*");
shortcuts.add(shortcut);
}
else if ("error".equals(name))
{
handleError();
}
}
} while (eventType != XmlPullParser.END_DOCUMENT);
validate();
if (!changed)
{
return null;
}
long t1 = System.currentTimeMillis();
Log.d(TAG, "Got " + artists.size() + " artist(s) in " + (t1 - t0) + "ms.");
String msg = this.context.getResources().getString(R.string.parser_artist_count, artists.size());
updateProgress(progressListener, msg);
return new Indexes(lastModified == null ? 0L : lastModified, ignoredArticles, shortcuts, artists);
}
}

View File

@ -82,7 +82,7 @@ class APIConverterTest {
MusicFolder(id, name)
private fun createArtist(id: Long = -1, name: String = "", starred: Calendar? = null): Artist
= Artist(id, name, starred)
= Artist(id = id, name = name, starred = starred)
private fun createIndex(name: String = "", artistList: List<Artist> = emptyList()): Index
= Index(name, artistList)