mirror of
https://gitlab.com/ultrasonic/ultrasonic.git
synced 2025-04-26 13:42:15 +03:00
Use new subsonic api getPodcasts call in RestMusicService.
Signed-off-by: Yahor Berdnikau <egorr.berd@gmail.com>
This commit is contained in:
parent
636968f03c
commit
ba0152bbca
@ -91,4 +91,29 @@ public class PodcastsChannel implements Serializable
|
||||
public String toString() {
|
||||
return getTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
PodcastsChannel that = (PodcastsChannel) o;
|
||||
|
||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||
if (title != null ? !title.equals(that.title) : that.title != null) return false;
|
||||
if (url != null ? !url.equals(that.url) : that.url != null) return false;
|
||||
if (description != null ? !description.equals(that.description) : that.description != null)
|
||||
return false;
|
||||
return status != null ? status.equals(that.status) : that.status == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id != null ? id.hashCode() : 0;
|
||||
result = 31 * result + (title != null ? title.hashCode() : 0);
|
||||
result = 31 * result + (url != null ? url.hashCode() : 0);
|
||||
result = 31 * result + (description != null ? description.hashCode() : 0);
|
||||
result = 31 * result + (status != null ? status.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -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.models.MusicDirectoryChild;
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetAlbumResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetArtistResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetArtistsResponse;
|
||||
@ -63,6 +64,7 @@ import org.moire.ultrasonic.api.subsonic.response.GetIndexesResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.GetMusicDirectoryResponse;
|
||||
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.LicenseResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.MusicFoldersResponse;
|
||||
import org.moire.ultrasonic.api.subsonic.response.SearchResponse;
|
||||
@ -75,6 +77,7 @@ import org.moire.ultrasonic.data.APIIndexesConverter;
|
||||
import org.moire.ultrasonic.data.APIMusicDirectoryConverter;
|
||||
import org.moire.ultrasonic.data.APIMusicFolderConverter;
|
||||
import org.moire.ultrasonic.data.APIPlaylistConverter;
|
||||
import org.moire.ultrasonic.data.APIPodcastConverter;
|
||||
import org.moire.ultrasonic.data.APISearchConverter;
|
||||
import org.moire.ultrasonic.domain.Bookmark;
|
||||
import org.moire.ultrasonic.domain.ChatMessage;
|
||||
@ -99,8 +102,6 @@ import org.moire.ultrasonic.service.parser.GenreParser;
|
||||
import org.moire.ultrasonic.service.parser.JukeboxStatusParser;
|
||||
import org.moire.ultrasonic.service.parser.LyricsParser;
|
||||
import org.moire.ultrasonic.service.parser.MusicDirectoryParser;
|
||||
import org.moire.ultrasonic.service.parser.PodcastEpisodeParser;
|
||||
import org.moire.ultrasonic.service.parser.PodcastsChannelsParser;
|
||||
import org.moire.ultrasonic.service.parser.RandomSongsParser;
|
||||
import org.moire.ultrasonic.service.parser.SearchResult2Parser;
|
||||
import org.moire.ultrasonic.service.parser.ShareParser;
|
||||
@ -526,41 +527,6 @@ public class RESTMusicService implements MusicService
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PodcastsChannel> getPodcastsChannels(boolean refresh, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
Reader reader = getReader(context, progressListener, "getPodcasts", null,"includeEpisodes", "false");
|
||||
try {
|
||||
return new PodcastsChannelsParser(context).parse(reader, progressListener);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getPodcastEpisodes(String podcastChannelId, Context context, ProgressListener progressListener) throws Exception {
|
||||
|
||||
List<String> names = new ArrayList<String>();
|
||||
names.add("id");
|
||||
names.add("includeEpisodes");
|
||||
List<Object> values = new ArrayList<Object>();
|
||||
values.add(podcastChannelId);
|
||||
values.add("true");
|
||||
|
||||
// TODO
|
||||
Reader reader = getReader(context, progressListener, "getPodcasts", null, names,values);
|
||||
//Reader reader = GetPodcastEpisodesTestReaderProvider.getReader();
|
||||
try {
|
||||
return new PodcastEpisodeParser(context).parse(reader, progressListener);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Playlist> getPlaylists(boolean refresh,
|
||||
Context context,
|
||||
@ -618,7 +584,47 @@ public class RESTMusicService implements MusicService
|
||||
checkResponseSuccessful(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public List<PodcastsChannel> getPodcastsChannels(boolean refresh,
|
||||
Context context,
|
||||
ProgressListener progressListener)
|
||||
throws Exception {
|
||||
updateProgressListener(progressListener, R.string.parser_reading);
|
||||
Response<GetPodcastsResponse> response = subsonicAPIClient.getApi()
|
||||
.getPodcasts(false, null).execute();
|
||||
checkResponseSuccessful(response);
|
||||
|
||||
return APIPodcastConverter.toDomainEntitiesList(response.body().getPodcastChannels());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getPodcastEpisodes(String podcastChannelId,
|
||||
Context context,
|
||||
ProgressListener progressListener) throws Exception {
|
||||
if (podcastChannelId == null) {
|
||||
throw new IllegalArgumentException("Podcast channel id is null!");
|
||||
}
|
||||
|
||||
updateProgressListener(progressListener, R.string.parser_reading);
|
||||
Response<GetPodcastsResponse> response = subsonicAPIClient.getApi()
|
||||
.getPodcasts(true, Long.valueOf(podcastChannelId)).execute();
|
||||
checkResponseSuccessful(response);
|
||||
|
||||
List<MusicDirectoryChild> podcastEntries = response.body().getPodcastChannels().get(0)
|
||||
.getEpisodeList();
|
||||
MusicDirectory musicDirectory = new MusicDirectory();
|
||||
for (MusicDirectoryChild podcastEntry : podcastEntries) {
|
||||
if (!"skipped".equals(podcastEntry.getStatus()) &&
|
||||
!"error".equals(podcastEntry.getStatus())) {
|
||||
MusicDirectory.Entry entry = APIMusicDirectoryConverter.toDomainEntity(podcastEntry);
|
||||
entry.setTrack(null);
|
||||
musicDirectory.addChild(entry);
|
||||
}
|
||||
}
|
||||
return musicDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkServerVersion(context, "1.2", "Lyrics not supported.");
|
||||
|
@ -1,143 +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.domain.PodcastEpisode;
|
||||
import org.moire.ultrasonic.domain.PodcastsChannel;
|
||||
import org.moire.ultrasonic.util.ProgressListener;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class PodcastEpisodeParser extends AbstractParser
|
||||
{
|
||||
|
||||
public PodcastEpisodeParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public MusicDirectory parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
|
||||
MusicDirectory musicDirectory = new MusicDirectory();
|
||||
SortedMap<Date,MusicDirectory.Entry> sortedEntries = new TreeMap<Date, MusicDirectory.Entry>();
|
||||
|
||||
Locale currentLocale = getContext().getResources().getConfiguration().locale;
|
||||
|
||||
DateFormat shortDateFormat = DateFormat.getDateTimeInstance(
|
||||
DateFormat.SHORT,
|
||||
DateFormat.SHORT, currentLocale);
|
||||
DateFormat parseDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
|
||||
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String tag = getElementName();
|
||||
if ("episode".equals(tag))
|
||||
{
|
||||
String status = get("status");
|
||||
if (!"skipped".equals(status) && !"error".equals(status)) {
|
||||
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
||||
String streamId = get("streamId");
|
||||
entry.setId(streamId);
|
||||
entry.setIsDirectory(Boolean.parseBoolean(get("isDir")));
|
||||
entry.setIsVideo(Boolean.parseBoolean(get("isVideo")));
|
||||
entry.setType(get("type"));
|
||||
entry.setPath(get("path"));
|
||||
entry.setSuffix(get("suffix"));
|
||||
String size = get("size");
|
||||
if (size != null) {
|
||||
entry.setSize(Long.parseLong(size));
|
||||
}
|
||||
entry.setCoverArt(get("coverArt"));
|
||||
entry.setAlbum(get("album"));
|
||||
entry.setTitle(get("title"));
|
||||
entry.setAlbumId(get("albumId"));
|
||||
entry.setArtist(get("artist"));
|
||||
entry.setArtistId(get("artistId"));
|
||||
String bitRate = get("bitRate");
|
||||
if (bitRate != null) {
|
||||
entry.setBitRate(Integer.parseInt(get("bitRate")));
|
||||
}
|
||||
entry.setContentType(get("contentType"));
|
||||
String duration = get("duration");
|
||||
if (duration != null) {
|
||||
entry.setDuration(Long.parseLong(duration));
|
||||
}
|
||||
entry.setGenre(get("genre"));
|
||||
entry.setParent(get("parent"));
|
||||
entry.setCreated("created");
|
||||
|
||||
|
||||
String publishDate = get("publishDate");
|
||||
if (publishDate != null) {
|
||||
try {
|
||||
Date publishDateDate = parseDateFormat.parse(publishDate);
|
||||
entry.setArtist(shortDateFormat.format(publishDateDate));
|
||||
sortedEntries.put(publishDateDate, entry);
|
||||
} catch (Exception e) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ("error".equals(tag))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
for (Date pubDate : sortedEntries.keySet()) {
|
||||
musicDirectory.addFirst(sortedEntries.get(pubDate));
|
||||
}
|
||||
return musicDirectory;
|
||||
}
|
||||
}
|
||||
|
@ -1,81 +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.Playlist;
|
||||
import org.moire.ultrasonic.domain.PodcastsChannel;
|
||||
import org.moire.ultrasonic.util.ProgressListener;
|
||||
import org.moire.ultrasonic.view.PlaylistAdapter;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class PodcastsChannelsParser extends AbstractParser
|
||||
{
|
||||
|
||||
public PodcastsChannelsParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public List<PodcastsChannel> parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
List<PodcastsChannel> result = new ArrayList<PodcastsChannel>();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String tag = getElementName();
|
||||
if ("channel".equals(tag))
|
||||
{
|
||||
String id = get("id");
|
||||
String title = get("title");
|
||||
String url = get("url");
|
||||
String description = get("description");
|
||||
String status = get("status");
|
||||
result.add(new PodcastsChannel(id,title, url,description,status));
|
||||
}
|
||||
else if ("error".equals(tag))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -5,8 +5,15 @@ package org.moire.ultrasonic.data
|
||||
|
||||
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
|
||||
import org.moire.ultrasonic.domain.MusicDirectory
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import org.moire.ultrasonic.api.subsonic.models.MusicDirectory as APIMusicDirectory
|
||||
|
||||
internal val dateFormat: DateFormat by lazy {
|
||||
SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault())
|
||||
}
|
||||
|
||||
fun MusicDirectoryChild.toDomainEntity(): MusicDirectory.Entry = MusicDirectory.Entry().apply {
|
||||
id = this@toDomainEntity.id.toString()
|
||||
parent = this@toDomainEntity.parent.toString()
|
||||
@ -33,6 +40,12 @@ fun MusicDirectoryChild.toDomainEntity(): MusicDirectory.Entry = MusicDirectory.
|
||||
starred = this@toDomainEntity.starred != null
|
||||
discNumber = this@toDomainEntity.discNumber
|
||||
type = this@toDomainEntity.type
|
||||
if (this@toDomainEntity.streamId >= 0) {
|
||||
id = this@toDomainEntity.streamId.toString()
|
||||
}
|
||||
if (this@toDomainEntity.publishDate != null) {
|
||||
artist = dateFormat.format(this@toDomainEntity.publishDate!!.time)
|
||||
}
|
||||
}
|
||||
|
||||
fun APIMusicDirectory.toDomainEntity(): MusicDirectory = MusicDirectory().apply {
|
||||
|
@ -0,0 +1,13 @@
|
||||
// Converts podcasts entities from [org.moire.ultrasonic.api.subsonic.SubsonicAPIClient]
|
||||
// to app domain entities.
|
||||
@file:JvmName("APIPodcastConverter")
|
||||
package org.moire.ultrasonic.data
|
||||
|
||||
import org.moire.ultrasonic.api.subsonic.models.PodcastChannel
|
||||
import org.moire.ultrasonic.domain.PodcastsChannel
|
||||
|
||||
fun PodcastChannel.toDomainEntity(): PodcastsChannel = PodcastsChannel(
|
||||
this.id.toString(), this.title, this.url, this.description, this.status)
|
||||
|
||||
fun List<PodcastChannel>.toDomainEntitiesList(): List<PodcastsChannel> = this
|
||||
.map { it.toDomainEntity() }
|
@ -69,4 +69,17 @@ class APIMusicDirectoryConverterTest {
|
||||
type `should equal to` entity.type
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Should convert MusicDirectoryChild podact entity`() {
|
||||
val entity = MusicDirectoryChild(id = 584, streamId = 394,
|
||||
artist = "some-artist", publishDate = Calendar.getInstance())
|
||||
|
||||
val convertedEntity = entity.toDomainEntity()
|
||||
|
||||
with(convertedEntity) {
|
||||
id `should equal to` entity.streamId.toString()
|
||||
artist `should equal to` dateFormat.format(entity.publishDate?.time)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
@file:Suppress("IllegalIdentifier")
|
||||
|
||||
package org.moire.ultrasonic.data
|
||||
|
||||
import org.amshove.kluent.`should equal to`
|
||||
import org.amshove.kluent.`should equal`
|
||||
import org.junit.Test
|
||||
import org.moire.ultrasonic.api.subsonic.models.PodcastChannel
|
||||
|
||||
/**
|
||||
* Unit test for extension functions in [APIPodcastConverter.kt] file.
|
||||
*/
|
||||
class APIPodcastConverterTest {
|
||||
@Test
|
||||
fun `Should convert podcast channel entity to domain entity`() {
|
||||
val entity = PodcastChannel(id = 452L, url = "some-url", title = "some-title",
|
||||
description = "some-description", coverArt = "cA", originalImageUrl = "image-url",
|
||||
status = "podcast-status", errorMessage = "some-error-message")
|
||||
|
||||
val converterEntity = entity.toDomainEntity()
|
||||
|
||||
with(converterEntity) {
|
||||
id = entity.id.toString()
|
||||
description = entity.description
|
||||
status = entity.status
|
||||
title = entity.title
|
||||
url = entity.url
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Should convert list of podcasts channels to domain entites list`() {
|
||||
val entitiesList = listOf(
|
||||
PodcastChannel(id = 932L, title = "title1"),
|
||||
PodcastChannel(id = 12L, title = "title2"))
|
||||
|
||||
val converted = entitiesList.toDomainEntitiesList()
|
||||
|
||||
with(converted) {
|
||||
size `should equal to` entitiesList.size
|
||||
this[0] `should equal` entitiesList[0].toDomainEntity()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user