mirror of
https://gitlab.com/ultrasonic/ultrasonic.git
synced 2025-04-18 02:02:23 +03:00
Merge pull request #62 from ultrasonic/add-get-songs-by-genre
Add get songs by genre
This commit is contained in:
commit
200a61fedc
@ -0,0 +1,82 @@
|
||||
package org.moire.ultrasonic.api.subsonic
|
||||
|
||||
import org.amshove.kluent.`should equal to`
|
||||
import org.amshove.kluent.`should equal`
|
||||
import org.junit.Test
|
||||
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
|
||||
|
||||
/**
|
||||
* Integration test for [SubsonicAPIDefinition.getSongsByGenre] call.
|
||||
*/
|
||||
class SubsonicApiGetSongsByGenreTest : SubsonicAPIClientTest() {
|
||||
@Test
|
||||
fun `Should handle error response`() {
|
||||
val response = checkErrorCallParsed(mockWebServerRule) {
|
||||
client.api.getSongsByGenre("Metal").execute()
|
||||
}
|
||||
|
||||
response.songsList `should equal` emptyList()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Should handle ok response`() {
|
||||
mockWebServerRule.enqueueResponse("get_songs_by_genre_ok.json")
|
||||
|
||||
val response = client.api.getSongsByGenre("Trance").execute()
|
||||
|
||||
assertResponseSuccessful(response)
|
||||
response.body().songsList.size `should equal to` 2
|
||||
with(response.body().songsList) {
|
||||
this[0] `should equal` MusicDirectoryChild(id = 575, parent = 576, isDir = false,
|
||||
title = "Time Machine (Vadim Zhukov Remix)", album = "668",
|
||||
artist = "Tasadi", year = 2008, genre = "Trance", size = 22467672,
|
||||
contentType = "audio/mpeg", suffix = "mp3", duration = 561, bitRate = 320,
|
||||
path = "Tasadi/668/00 Time Machine (Vadim Zhukov Remix).mp3",
|
||||
isVideo = false, playCount = 0, created = parseDate("2016-10-23T21:58:29.000Z"),
|
||||
albumId = 0, artistId = 0, type = "music")
|
||||
this[1] `should equal` MusicDirectoryChild(id = 621, parent = 622, isDir = false,
|
||||
title = "My Heart (Vadim Zhukov Remix)", album = "668",
|
||||
artist = "DJ Polyakov PPK Feat Kate Cameron", year = 2009, genre = "Trance",
|
||||
size = 26805932, contentType = "audio/mpeg", suffix = "mp3", duration = 670,
|
||||
bitRate = 320,
|
||||
path = "DJ Polyakov PPK Feat Kate Cameron/668/00 My Heart (Vadim Zhukov Remix).mp3",
|
||||
isVideo = false, playCount = 2, created = parseDate("2016-10-23T21:58:29.000Z"),
|
||||
albumId = 5, artistId = 4, type = "music")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Should pass genre in request param`() {
|
||||
val genre = "Rock"
|
||||
mockWebServerRule.assertRequestParam(expectedParam = "genre=$genre") {
|
||||
client.api.getSongsByGenre(genre = genre).execute()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Should pass count in request param`() {
|
||||
val count = 494
|
||||
|
||||
mockWebServerRule.assertRequestParam(expectedParam = "count=$count") {
|
||||
client.api.getSongsByGenre("Trance", count = count).execute()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Should pass offset in request param`() {
|
||||
val offset = 31
|
||||
|
||||
mockWebServerRule.assertRequestParam(expectedParam = "offset=$offset") {
|
||||
client.api.getSongsByGenre("Trance", offset = offset).execute()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Should pass music folder id in request param`() {
|
||||
val musicFolderId = 1010L
|
||||
|
||||
mockWebServerRule.assertRequestParam(expectedParam = "musicFolderId=$musicFolderId") {
|
||||
client.api.getSongsByGenre("Trance", musicFolderId = musicFolderId).execute()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
{
|
||||
"subsonic-response" : {
|
||||
"status" : "ok",
|
||||
"version" : "1.15.0",
|
||||
"songsByGenre" : {
|
||||
"song" : [ {
|
||||
"id" : "575",
|
||||
"parent" : "576",
|
||||
"isDir" : false,
|
||||
"title" : "Time Machine (Vadim Zhukov Remix)",
|
||||
"album" : "668",
|
||||
"artist" : "Tasadi",
|
||||
"year" : 2008,
|
||||
"genre" : "Trance",
|
||||
"size" : 22467672,
|
||||
"contentType" : "audio/mpeg",
|
||||
"suffix" : "mp3",
|
||||
"duration" : 561,
|
||||
"bitRate" : 320,
|
||||
"path" : "Tasadi/668/00 Time Machine (Vadim Zhukov Remix).mp3",
|
||||
"isVideo" : false,
|
||||
"playCount" : 0,
|
||||
"created" : "2016-10-23T21:58:29.000Z",
|
||||
"albumId" : "0",
|
||||
"artistId" : "0",
|
||||
"type" : "music"
|
||||
}, {
|
||||
"id" : "621",
|
||||
"parent" : "622",
|
||||
"isDir" : false,
|
||||
"title" : "My Heart (Vadim Zhukov Remix)",
|
||||
"album" : "668",
|
||||
"artist" : "DJ Polyakov PPK Feat Kate Cameron",
|
||||
"year" : 2009,
|
||||
"genre" : "Trance",
|
||||
"size" : 26805932,
|
||||
"contentType" : "audio/mpeg",
|
||||
"suffix" : "mp3",
|
||||
"duration" : 670,
|
||||
"bitRate" : 320,
|
||||
"path" : "DJ Polyakov PPK Feat Kate Cameron/668/00 My Heart (Vadim Zhukov Remix).mp3",
|
||||
"isVideo" : false,
|
||||
"playCount" : 2,
|
||||
"created" : "2016-10-23T21:58:29.000Z",
|
||||
"albumId" : "5",
|
||||
"artistId" : "4",
|
||||
"type" : "music"
|
||||
} ]
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,9 @@ import java.math.BigInteger
|
||||
import java.security.MessageDigest
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.security.SecureRandom
|
||||
import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
|
||||
private const val READ_TIMEOUT = 60_000L
|
||||
|
||||
/**
|
||||
* Subsonic API client that provides api access.
|
||||
@ -38,6 +41,7 @@ class SubsonicAPIClient(baseUrl: String,
|
||||
}
|
||||
|
||||
private val okHttpClient = OkHttpClient.Builder()
|
||||
.readTimeout(READ_TIMEOUT, MILLISECONDS)
|
||||
.addInterceptor { chain ->
|
||||
// Adds default request params
|
||||
val originalRequest = chain.request()
|
||||
|
@ -16,6 +16,7 @@ import org.moire.ultrasonic.api.subsonic.response.GetPlaylistResponse
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetPlaylistsResponse
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetPodcastsResponse
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetRandomSongsResponse
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetSongsByGenreResponse
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetStarredResponse
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetStarredTwoResponse
|
||||
import org.moire.ultrasonic.api.subsonic.response.JukeboxResponse
|
||||
@ -201,4 +202,11 @@ interface SubsonicAPIDefinition {
|
||||
|
||||
@GET("getGenres.view")
|
||||
fun getGenres(): Call<GenresResponse>
|
||||
|
||||
@GET("getSongsByGenre.view")
|
||||
fun getSongsByGenre(
|
||||
@Query("genre") genre: String,
|
||||
@Query("count") count: Int = 10,
|
||||
@Query("offset") offset: Int = 0,
|
||||
@Query("musicFolderId") musicFolderId: Long? = null): Call<GetSongsByGenreResponse>
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
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.MusicDirectoryChild
|
||||
|
||||
class GetSongsByGenreResponse(
|
||||
status: Status,
|
||||
version: SubsonicAPIVersions,
|
||||
error: SubsonicError?) : SubsonicResponse(status, version, error) {
|
||||
@JsonProperty("songsByGenre") private val songsByGenreList = SongsByGenreWrapper()
|
||||
|
||||
val songsList get() = songsByGenreList.songsList
|
||||
}
|
||||
|
||||
internal class SongsByGenreWrapper(
|
||||
@JsonProperty("song") val songsList: List<MusicDirectoryChild> = emptyList())
|
@ -71,6 +71,7 @@ import org.moire.ultrasonic.api.subsonic.response.GetPlaylistResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetPlaylistsResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetPodcastsResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetRandomSongsResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetSongsByGenreResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetStarredResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetStarredTwoResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.JukeboxResponse;
|
||||
@ -113,7 +114,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.MusicDirectoryParser;
|
||||
import org.moire.ultrasonic.service.parser.RandomSongsParser;
|
||||
import org.moire.ultrasonic.service.parser.SubsonicRESTException;
|
||||
import org.moire.ultrasonic.service.parser.UserInfoParser;
|
||||
import org.moire.ultrasonic.service.ssl.SSLSocketFactory;
|
||||
@ -1207,35 +1207,26 @@ public class RESTMusicService implements MusicService
|
||||
return ApiGenreConverter.toDomainEntityList(response.body().getGenresList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkServerVersion(context, "1.9", "Genres not supported.");
|
||||
@Override
|
||||
public MusicDirectory getSongsByGenre(String genre,
|
||||
int count,
|
||||
int offset,
|
||||
Context context,
|
||||
ProgressListener progressListener) throws Exception {
|
||||
if (genre == null) {
|
||||
throw new IllegalArgumentException("Genre is null");
|
||||
}
|
||||
|
||||
HttpParams params = new BasicHttpParams();
|
||||
HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_RANDOM_SONGS);
|
||||
updateProgressListener(progressListener, R.string.parser_reading);
|
||||
Response<GetSongsByGenreResponse> response = subsonicAPIClient.getApi()
|
||||
.getSongsByGenre(genre, count, offset, null)
|
||||
.execute();
|
||||
checkResponseSuccessful(response);
|
||||
|
||||
List<String> parameterNames = new ArrayList<String>();
|
||||
List<Object> parameterValues = new ArrayList<Object>();
|
||||
|
||||
parameterNames.add("genre");
|
||||
parameterValues.add(genre);
|
||||
parameterNames.add("count");
|
||||
parameterValues.add(count);
|
||||
parameterNames.add("offset");
|
||||
parameterValues.add(offset);
|
||||
|
||||
Reader reader = getReader(context, progressListener, "getSongsByGenre", params, parameterNames, parameterValues);
|
||||
|
||||
try
|
||||
{
|
||||
return new RandomSongsParser(context).parse(reader, progressListener);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
MusicDirectory result = new MusicDirectory();
|
||||
result.addAll(APIMusicDirectoryConverter.toDomainEntityList(response.body().getSongsList()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserInfo getUser(String username, Context context, ProgressListener progressListener) throws Exception
|
||||
|
@ -1,72 +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 org.moire.ultrasonic.R;
|
||||
import org.moire.ultrasonic.domain.MusicDirectory;
|
||||
import org.moire.ultrasonic.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class RandomSongsParser extends MusicDirectoryEntryParser
|
||||
{
|
||||
|
||||
public RandomSongsParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public MusicDirectory parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
MusicDirectory dir = new MusicDirectory();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("song".equals(name))
|
||||
{
|
||||
dir.addChild(parseEntry("", false, 0));
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user