mirror of
https://github.com/ultrasonic/ultrasonic
synced 2025-02-03 02:27:31 +01:00
Merge pull request #25 from ultrasonic/use-get-artists
Use getArtists new api implementation call
This commit is contained in:
commit
6b8d953751
@ -164,17 +164,18 @@ class SubsonicAPIClientTest {
|
|||||||
lastModified `should equal` 1491069027523
|
lastModified `should equal` 1491069027523
|
||||||
ignoredArticles `should equal` "The El La Los Las Le Les"
|
ignoredArticles `should equal` "The El La Los Las Le Les"
|
||||||
shortcutList `should equal` listOf(
|
shortcutList `should equal` listOf(
|
||||||
Artist(889L, "podcasts", null),
|
Artist(id = 889L, name = "podcasts"),
|
||||||
Artist(890L, "audiobooks", null)
|
Artist(id = 890L, name = "audiobooks")
|
||||||
)
|
)
|
||||||
indexList `should equal` mutableListOf(
|
indexList `should equal` mutableListOf(
|
||||||
Index("A", listOf(
|
Index("A", listOf(
|
||||||
Artist(50L, "Ace Of Base", parseDate("2017-04-02T20:16:29.815Z")),
|
Artist(id = 50L, name = "Ace Of Base",
|
||||||
Artist(379L, "A Perfect Circle", null)
|
starred = parseDate("2017-04-02T20:16:29.815Z")),
|
||||||
|
Artist(id = 379L, name = "A Perfect Circle")
|
||||||
)),
|
)),
|
||||||
Index("H", listOf(
|
Index("H", listOf(
|
||||||
Artist(299, "Haddaway", null),
|
Artist(id = 299, name = "Haddaway"),
|
||||||
Artist(297, "Halestorm", null)
|
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) {
|
private fun enqueueResponse(resourceName: String) {
|
||||||
mockWebServerRule.mockWebServer.enqueue(MockResponse()
|
mockWebServerRule.mockWebServer.enqueue(MockResponse()
|
||||||
.setBody(loadJsonResponse(resourceName)))
|
.setBody(loadJsonResponse(resourceName)))
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package org.moire.ultrasonic.api.subsonic
|
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.GetIndexesResponse
|
||||||
import org.moire.ultrasonic.api.subsonic.response.GetMusicDirectoryResponse
|
import org.moire.ultrasonic.api.subsonic.response.GetMusicDirectoryResponse
|
||||||
import org.moire.ultrasonic.api.subsonic.response.LicenseResponse
|
import org.moire.ultrasonic.api.subsonic.response.LicenseResponse
|
||||||
@ -30,4 +31,7 @@ interface SubsonicAPIDefinition {
|
|||||||
|
|
||||||
@GET("getMusicDirectory.view")
|
@GET("getMusicDirectory.view")
|
||||||
fun getMusicDirectory(@Query("id") id: Long): Call<GetMusicDirectoryResponse>
|
fun getMusicDirectory(@Query("id") id: Long): Call<GetMusicDirectoryResponse>
|
||||||
|
|
||||||
|
@GET("getArtists.view")
|
||||||
|
fun getArtists(@Query("musicFolderId") musicFolderId: Long?): Call<GetArtistsResponse>
|
||||||
}
|
}
|
||||||
|
@ -4,4 +4,6 @@ import java.util.Calendar
|
|||||||
|
|
||||||
data class Artist(val id: Long = -1,
|
data class Artist(val id: Long = -1,
|
||||||
val name: String = "",
|
val name: String = "",
|
||||||
val starred: Calendar?)
|
val coverArt: String = "",
|
||||||
|
val albumCount: Int = 0,
|
||||||
|
val starred: Calendar? = null)
|
||||||
|
@ -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)
|
@ -56,6 +56,7 @@ import org.apache.http.protocol.ExecutionContext;
|
|||||||
import org.apache.http.protocol.HttpContext;
|
import org.apache.http.protocol.HttpContext;
|
||||||
import org.moire.ultrasonic.R;
|
import org.moire.ultrasonic.R;
|
||||||
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient;
|
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.GetIndexesResponse;
|
||||||
import org.moire.ultrasonic.api.subsonic.response.LicenseResponse;
|
import org.moire.ultrasonic.api.subsonic.response.LicenseResponse;
|
||||||
import org.moire.ultrasonic.api.subsonic.response.MusicFoldersResponse;
|
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.ChatMessageParser;
|
||||||
import org.moire.ultrasonic.service.parser.ErrorParser;
|
import org.moire.ultrasonic.service.parser.ErrorParser;
|
||||||
import org.moire.ultrasonic.service.parser.GenreParser;
|
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.JukeboxStatusParser;
|
||||||
import org.moire.ultrasonic.service.parser.LyricsParser;
|
import org.moire.ultrasonic.service.parser.LyricsParser;
|
||||||
import org.moire.ultrasonic.service.parser.MusicDirectoryParser;
|
import org.moire.ultrasonic.service.parser.MusicDirectoryParser;
|
||||||
@ -234,6 +234,21 @@ public class RESTMusicService implements MusicService
|
|||||||
return musicFolders;
|
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
|
@Override
|
||||||
public Indexes getIndexes(String musicFolderId,
|
public Indexes getIndexes(String musicFolderId,
|
||||||
boolean refresh,
|
boolean refresh,
|
||||||
@ -269,68 +284,38 @@ public class RESTMusicService implements MusicService
|
|||||||
return String.format(Locale.US, "indexes-%d.ser", Math.abs(s.hashCode()));
|
return String.format(Locale.US, "indexes-%d.ser", Math.abs(s.hashCode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Indexes getArtists(boolean refresh, Context context, ProgressListener progressListener) throws Exception
|
public Indexes getArtists(boolean refresh,
|
||||||
{
|
Context context,
|
||||||
checkServerVersion(context, "1.8", "Artists by ID3 tag not supported.");
|
ProgressListener progressListener) throws Exception {
|
||||||
|
Indexes cachedArtists = readCachedArtists(context);
|
||||||
|
if (cachedArtists != null &&
|
||||||
|
!refresh) {
|
||||||
|
return cachedArtists;
|
||||||
|
}
|
||||||
|
|
||||||
Indexes cachedArtists = readCachedArtists(context);
|
Response<GetArtistsResponse> response = subsonicAPIClient.getApi().getArtists(null).execute();
|
||||||
if (cachedArtists != null && !refresh)
|
checkResponseSuccessful(response);
|
||||||
{
|
|
||||||
return cachedArtists;
|
|
||||||
}
|
|
||||||
|
|
||||||
Reader reader = getReader(context, progressListener, "getArtists", null);
|
Indexes indexes = APIConverter.toDomainEntity(response.body().getIndexes());
|
||||||
try
|
writeCachedArtists(context, indexes);
|
||||||
{
|
return indexes;
|
||||||
Indexes indexes = new IndexesParser(context).parse(reader, progressListener);
|
}
|
||||||
if (indexes != null)
|
|
||||||
{
|
|
||||||
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>());
|
private static Indexes readCachedArtists(Context context) {
|
||||||
}
|
String filename = getCachedArtistsFilename(context);
|
||||||
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);
|
|
||||||
return FileUtil.deserialize(context, filename);
|
return FileUtil.deserialize(context, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void writeCachedMusicFolders(Context context, List<MusicFolder> musicFolders) {
|
private static void writeCachedArtists(Context context, Indexes artists) {
|
||||||
String filename = getCachedMusicFoldersFilename(context);
|
String filename = getCachedArtistsFilename(context);
|
||||||
FileUtil.serialize(context, new ArrayList<>(musicFolders), filename);
|
FileUtil.serialize(context, artists, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getCachedMusicFoldersFilename(Context context)
|
private static String getCachedArtistsFilename(Context context) {
|
||||||
{
|
String s = Util.getRestUrl(context, null);
|
||||||
String s = Util.getRestUrl(context, null);
|
return String.format(Locale.US, "indexes-%d.ser", Math.abs(s.hashCode()));
|
||||||
return String.format("musicFolders-%d.ser", Math.abs(s.hashCode()));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception
|
public void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -82,7 +82,7 @@ class APIConverterTest {
|
|||||||
MusicFolder(id, name)
|
MusicFolder(id, name)
|
||||||
|
|
||||||
private fun createArtist(id: Long = -1, name: String = "", starred: Calendar? = null): Artist
|
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
|
private fun createIndex(name: String = "", artistList: List<Artist> = emptyList()): Index
|
||||||
= Index(name, artistList)
|
= Index(name, artistList)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user