- Switched from subsonic-response in xml to response in json

- Retrofitting of all Subsonic models
This commit is contained in:
antonio 2023-03-08 19:19:09 +01:00
parent ca15f51c85
commit 521c51b17e
85 changed files with 682 additions and 898 deletions

View file

@ -7,11 +7,11 @@ android {
buildToolsVersion '33.0.0' buildToolsVersion '33.0.0'
defaultConfig { defaultConfig {
applicationId "com.cappielloantonio.playforsubsonic" applicationId "com.cappielloantonio.playforsubsonic.test"
minSdkVersion 26 minSdkVersion 26
targetSdkVersion 33 targetSdkVersion 33
versionCode 4 versionCode 4
versionName "2.1.0" versionName "3.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -66,33 +66,27 @@ dependencies {
implementation "com.arthurivanets.adapster:adapster:1.0.13" implementation "com.arthurivanets.adapster:adapster:1.0.13"
// Glide // Glide
implementation 'com.github.bumptech.glide:glide:4.14.2' implementation 'com.github.bumptech.glide:glide:4.15.0'
implementation 'com.github.bumptech.glide:annotations:4.14.2' implementation 'com.github.bumptech.glide:annotations:4.15.0'
// Media3 // Media3
implementation 'androidx.media3:media3-session:1.0.0-rc01' implementation 'androidx.media3:media3-session:1.0.0-rc02'
implementation 'androidx.media3:media3-common:1.0.0-rc01' implementation 'androidx.media3:media3-common:1.0.0-rc02'
implementation 'androidx.media3:media3-exoplayer:1.0.0-rc01' implementation 'androidx.media3:media3-exoplayer:1.0.0-rc02'
implementation 'androidx.media3:media3-ui:1.0.0-rc01' implementation 'androidx.media3:media3-ui:1.0.0-rc02'
implementation 'androidx.media3:media3-cast:1.0.0-rc01' implementation 'androidx.media3:media3-cast:1.0.0-rc02'
annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2' annotationProcessor 'com.github.bumptech.glide:compiler:4.15.0'
annotationProcessor 'androidx.room:room-compiler:2.5.0' annotationProcessor 'androidx.room:room-compiler:2.5.0'
// Retrofit // Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.6' implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.6'
implementation 'com.tickaroo.tikxml:retrofit-converter:0.8.15' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
// XMLParser
implementation 'com.tickaroo.tikxml:annotation:0.9.0_11-SNAPSHOT'
implementation 'com.tickaroo.tikxml:core:0.9.0_11-SNAPSHOT'
annotationProcessor 'com.tickaroo.tikxml:processor:0.9.0_11-SNAPSHOT'
implementation 'com.tickaroo.tikxml:converter-date-rfc3339:0.9.0_11-SNAPSHOT'
// Crash Report // Crash Report
// debugImplementation 'com.balsikandar.android:crashreporter:1.1.0' // debugImplementation 'com.balsikandar.android:crashreporter:1.1.0'
// DB debug // DB debug
// debugImplementation 'com.amitshekhar.android:debug-db:1.0.6' debugImplementation 'com.amitshekhar.android:debug-db:1.0.6'
} }

View file

@ -9,7 +9,6 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.load.resource.bitmap.CenterCrop; import com.bumptech.glide.load.resource.bitmap.CenterCrop;
@ -83,7 +82,7 @@ public class ArtistSimilarAdapter extends RecyclerView.Adapter<ArtistSimilarAdap
.into(cover); .into(cover);
} }
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { public class ViewHolder extends RecyclerView.ViewHolder {
TextView textArtistName; TextView textArtistName;
ImageView cover; ImageView cover;
@ -93,27 +92,12 @@ public class ArtistSimilarAdapter extends RecyclerView.Adapter<ArtistSimilarAdap
textArtistName = itemView.findViewById(R.id.artist_name_label); textArtistName = itemView.findViewById(R.id.artist_name_label);
cover = itemView.findViewById(R.id.similar_artist_cover_image_view); cover = itemView.findViewById(R.id.similar_artist_cover_image_view);
itemView.setOnClickListener(this); itemView.setOnClickListener(v -> onClick());
itemView.setOnLongClickListener(this); itemView.setOnLongClickListener(v -> onLongClick());
textArtistName.setSelected(true); textArtistName.setSelected(true);
} }
@Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putParcelable("artist_object", artists.get(getBindingAdapterPosition()));
Navigation.findNavController(view).navigate(R.id.artistPageFragment, bundle);
}
@Override
public boolean onLongClick(View view) {
Bundle bundle = new Bundle();
bundle.putParcelable("artist_object", artists.get(getBindingAdapterPosition()));
Navigation.findNavController(view).navigate(R.id.artistBottomSheetDialog, bundle);
return true;
}
public void onClick() { public void onClick() {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelable("artist_object", artists.get(getBindingAdapterPosition())); bundle.putParcelable("artist_object", artists.get(getBindingAdapterPosition()));

View file

@ -78,8 +78,6 @@ public class PlaylistDialogHorizontalAdapter extends RecyclerView.Adapter<Playli
} }
public void onClick() { public void onClick() {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelable("playlist_object", playlists.get(getBindingAdapterPosition())); bundle.putParcelable("playlist_object", playlists.get(getBindingAdapterPosition()));

View file

@ -22,7 +22,7 @@ import com.cappielloantonio.play.model.Server;
import com.cappielloantonio.play.subsonic.models.Playlist; import com.cappielloantonio.play.subsonic.models.Playlist;
@Database( @Database(
version = 48, version = 52,
entities = {Queue.class, Server.class, RecentSearch.class, Download.class, Playlist.class, Chronology.class} entities = {Queue.class, Server.class, RecentSearch.class, Download.class, Playlist.class, Chronology.class}
// autoMigrations = {@AutoMigration(from = 43, to = 44)} // autoMigrations = {@AutoMigration(from = 43, to = 44)}
) )

View file

@ -1,11 +1,14 @@
package com.cappielloantonio.play.model package com.cappielloantonio.play.model
import androidx.annotation.Keep import androidx.annotation.Keep
import androidx.media3.common.MediaItem
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.cappielloantonio.play.subsonic.models.Child import com.cappielloantonio.play.subsonic.models.Child
import com.cappielloantonio.play.util.Preferences
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
import java.util.*
@Keep @Keep
@Parcelize @Parcelize
@ -16,4 +19,39 @@ class Chronology(@PrimaryKey override val id: String) : Child(id) {
@ColumnInfo(name = "server") @ColumnInfo(name = "server")
var server: String? = null var server: String? = null
constructor(mediaItem: MediaItem) : this(mediaItem.mediaMetadata.extras!!.getString("id")!!) {
parentId = mediaItem.mediaMetadata.extras!!.getString("parentId")
isDir = mediaItem.mediaMetadata.extras!!.getBoolean("isDir")
title = mediaItem.mediaMetadata.extras!!.getString("title")
album = mediaItem.mediaMetadata.extras!!.getString("album")
artist = mediaItem.mediaMetadata.extras!!.getString("artist")
track = mediaItem.mediaMetadata.extras!!.getInt("track")
year = mediaItem.mediaMetadata.extras!!.getInt("year")
genre = mediaItem.mediaMetadata.extras!!.getString("genre")
coverArtId = mediaItem.mediaMetadata.extras!!.getString("coverArtId")
size = mediaItem.mediaMetadata.extras!!.getLong("size")
contentType = mediaItem.mediaMetadata.extras!!.getString("contentType")
suffix = mediaItem.mediaMetadata.extras!!.getString("suffix")
transcodedContentType = mediaItem.mediaMetadata.extras!!.getString("transcodedContentType")
transcodedSuffix = mediaItem.mediaMetadata.extras!!.getString("transcodedSuffix")
duration = mediaItem.mediaMetadata.extras!!.getInt("duration")
bitrate = mediaItem.mediaMetadata.extras!!.getInt("bitrate")
path = mediaItem.mediaMetadata.extras!!.getString("path")
isVideo = mediaItem.mediaMetadata.extras!!.getBoolean("isVideo")
userRating = mediaItem.mediaMetadata.extras!!.getInt("userRating")
averageRating = mediaItem.mediaMetadata.extras!!.getDouble("averageRating")
playCount = mediaItem.mediaMetadata.extras!!.getLong("playCount")
discNumber = mediaItem.mediaMetadata.extras!!.getInt("discNumber")
created = Date(mediaItem.mediaMetadata.extras!!.getLong("created"))
starred = Date(mediaItem.mediaMetadata.extras!!.getLong("starred"))
albumId = mediaItem.mediaMetadata.extras!!.getString("albumId")
artistId = mediaItem.mediaMetadata.extras!!.getString("artistId")
type = mediaItem.mediaMetadata.extras!!.getString("type")
bookmarkPosition = mediaItem.mediaMetadata.extras!!.getLong("bookmarkPosition")
originalWidth = mediaItem.mediaMetadata.extras!!.getInt("originalWidth")
originalHeight = mediaItem.mediaMetadata.extras!!.getInt("originalHeight")
server = Preferences.getServerId()
timestamp = Date().time
}
} }

View file

@ -11,16 +11,49 @@ import kotlinx.android.parcel.Parcelize
@Parcelize @Parcelize
@Entity(tableName = "queue") @Entity(tableName = "queue")
class Queue(override val id: String) : Child(id) { class Queue(override val id: String) : Child(id) {
@PrimaryKey(autoGenerate = true) @PrimaryKey
@ColumnInfo(name = "track_order") @ColumnInfo(name = "track_order")
var trackOrder: Int = 0 var trackOrder: Int = 0
@ColumnInfo(name = "last_play", defaultValue = "0") @ColumnInfo(name = "last_play")
var lastPlay: Long = 0 var lastPlay: Long = 0
@ColumnInfo(name = "playing_changed", defaultValue = "0") @ColumnInfo(name = "playing_changed")
var playingChanged: Long = 0 var playingChanged: Long = 0
@ColumnInfo(name = "stream_id") @ColumnInfo(name = "stream_id")
var streamId: String? = null var streamId: String? = null
constructor(child: Child) : this(child.id) {
parentId = child.parentId
isDir = child.isDir
title = child.title
album = child.album
artist = child.artist
track = child.track
year = child.year
genre = child.genre
coverArtId = child.coverArtId
size = child.size
contentType = child.contentType
suffix = child.suffix
transcodedContentType = child.transcodedContentType
transcodedSuffix = child.transcodedSuffix
duration = child.duration
bitrate = child.bitrate
path = child.path
isVideo = child.isVideo
userRating = child.userRating
averageRating = child.averageRating
playCount = child.playCount
discNumber = child.discNumber
created = child.created
starred = child.starred
albumId = child.albumId
artistId = child.artistId
type = child.type
bookmarkPosition = child.bookmarkPosition
originalWidth = child.originalWidth
originalHeight = child.originalHeight
}
} }

View file

@ -8,6 +8,7 @@ import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.interfaces.DecadesCallback; import com.cappielloantonio.play.interfaces.DecadesCallback;
import com.cappielloantonio.play.interfaces.MediaCallback; import com.cappielloantonio.play.interfaces.MediaCallback;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.AlbumID3; import com.cappielloantonio.play.subsonic.models.AlbumID3;
import com.cappielloantonio.play.subsonic.models.Child; import com.cappielloantonio.play.subsonic.models.Child;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
@ -32,21 +33,21 @@ public class AlbumRepository {
} }
public MutableLiveData<List<AlbumID3>> getAlbums(String type, int size, Integer fromYear, Integer toYear) { public MutableLiveData<List<AlbumID3>> getAlbums(String type, int size, Integer fromYear, Integer toYear) {
MutableLiveData<List<AlbumID3>> listLiveAlbums = new MutableLiveData<>(new ArrayList<>()); MutableLiveData<List<AlbumID3>> listLiveAlbums = new MutableLiveData<>();
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getAlbumSongListClient() .getAlbumSongListClient()
.getAlbumList2(type, size, 0, fromYear, toYear) .getAlbumList2(type, size, 0, fromYear, toYear)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getAlbumList2() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getAlbumList2() != null) {
listLiveAlbums.setValue(response.body().getAlbumList2().getAlbums()); listLiveAlbums.setValue(response.body().getSubsonicResponse().getAlbumList2().getAlbums());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -60,11 +61,11 @@ public class AlbumRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getAlbumSongListClient() .getAlbumSongListClient()
.getStarred2() .getStarred2()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getStarred2() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getStarred2() != null) {
List<AlbumID3> albums = response.body().getStarred2().getAlbums(); List<AlbumID3> albums = response.body().getSubsonicResponse().getStarred2().getAlbums();
if (random) { if (random) {
Collections.shuffle(albums); Collections.shuffle(albums);
@ -76,7 +77,7 @@ public class AlbumRepository {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -88,14 +89,14 @@ public class AlbumRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaAnnotationClient() .getMediaAnnotationClient()
.star(null, id, null) .star(null, id, null)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -105,14 +106,14 @@ public class AlbumRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaAnnotationClient() .getMediaAnnotationClient()
.unstar(null, id, null) .unstar(null, id, null)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -122,14 +123,14 @@ public class AlbumRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaAnnotationClient() .getMediaAnnotationClient()
.setRating(id, rating) .setRating(id, rating)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -141,20 +142,20 @@ public class AlbumRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getAlbum(id) .getAlbum(id)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
List<Child> tracks = new ArrayList<>(); List<Child> tracks = new ArrayList<>();
if (response.isSuccessful() && response.body() != null && response.body().getAlbum() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getAlbum() != null) {
tracks.addAll(response.body().getAlbum().getSongs()); tracks.addAll(response.body().getSubsonicResponse().getAlbum().getSongs());
} }
albumTracks.setValue(tracks); albumTracks.setValue(tracks);
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -168,18 +169,18 @@ public class AlbumRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getArtist(id) .getArtist(id)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getArtist() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getArtist() != null) {
List<AlbumID3> albums = response.body().getArtist().getAlbums(); List<AlbumID3> albums = response.body().getSubsonicResponse().getArtist().getAlbums();
albums.sort(Comparator.comparing(AlbumID3::getYear)); albums.sort(Comparator.comparing(AlbumID3::getYear));
artistsAlbum.setValue(albums); artistsAlbum.setValue(albums);
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -193,16 +194,16 @@ public class AlbumRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getAlbum(id) .getAlbum(id)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getAlbum() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getAlbum() != null) {
album.setValue(response.body().getAlbum()); album.setValue(response.body().getSubsonicResponse().getAlbum());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -214,20 +215,20 @@ public class AlbumRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getSimilarSongs2(album.getId(), count) .getSimilarSongs2(album.getId(), count)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
List<Child> songs = new ArrayList<>(); List<Child> songs = new ArrayList<>();
if (response.isSuccessful() && response.body() != null && response.body().getSimilarSongs2() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getSimilarSongs2() != null) {
songs.addAll(response.body().getSimilarSongs2().getSongs()); songs.addAll(response.body().getSubsonicResponse().getSimilarSongs2().getSongs());
} }
callback.onLoadMedia(songs); callback.onLoadMedia(songs);
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
callback.onLoadMedia(new ArrayList<>()); callback.onLoadMedia(new ArrayList<>());
} }
}); });
@ -259,16 +260,16 @@ public class AlbumRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getAlbumSongListClient() .getAlbumSongListClient()
.getAlbumList2("byYear", 1, 0, 1900, Calendar.getInstance().get(Calendar.YEAR)) .getAlbumList2("byYear", 1, 0, 1900, Calendar.getInstance().get(Calendar.YEAR))
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getAlbumList2() != null && response.body().getAlbumList2().getAlbums() != null && !response.body().getAlbumList2().getAlbums().isEmpty()) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getAlbumList2() != null && response.body().getSubsonicResponse().getAlbumList2().getAlbums() != null && !response.body().getSubsonicResponse().getAlbumList2().getAlbums().isEmpty()) {
callback.onLoadYear(response.body().getAlbumList2().getAlbums().get(0).getYear()); callback.onLoadYear(response.body().getSubsonicResponse().getAlbumList2().getAlbums().get(0).getYear());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
callback.onLoadYear(-1); callback.onLoadYear(-1);
} }
}); });
@ -278,12 +279,12 @@ public class AlbumRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getAlbumSongListClient() .getAlbumSongListClient()
.getAlbumList2("byYear", 1, 0, Calendar.getInstance().get(Calendar.YEAR), 1900) .getAlbumList2("byYear", 1, 0, Calendar.getInstance().get(Calendar.YEAR), 1900)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getAlbumList2() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getAlbumList2() != null) {
if (response.body().getAlbumList2().getAlbums().size() > 0 && !response.body().getAlbumList2().getAlbums().isEmpty()) { if (response.body().getSubsonicResponse().getAlbumList2().getAlbums().size() > 0 && !response.body().getSubsonicResponse().getAlbumList2().getAlbums().isEmpty()) {
callback.onLoadYear(response.body().getAlbumList2().getAlbums().get(0).getYear()); callback.onLoadYear(response.body().getSubsonicResponse().getAlbumList2().getAlbums().get(0).getYear());
} else { } else {
callback.onLoadYear(-1); callback.onLoadYear(-1);
} }
@ -291,7 +292,7 @@ public class AlbumRepository {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
callback.onLoadYear(-1); callback.onLoadYear(-1);
} }
}); });

View file

@ -7,12 +7,12 @@ import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.AlbumID3; import com.cappielloantonio.play.subsonic.models.AlbumID3;
import com.cappielloantonio.play.subsonic.models.ArtistID3; import com.cappielloantonio.play.subsonic.models.ArtistID3;
import com.cappielloantonio.play.subsonic.models.ArtistInfo2; import com.cappielloantonio.play.subsonic.models.ArtistInfo2;
import com.cappielloantonio.play.subsonic.models.Child; import com.cappielloantonio.play.subsonic.models.Child;
import com.cappielloantonio.play.subsonic.models.IndexID3; import com.cappielloantonio.play.subsonic.models.IndexID3;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -35,11 +35,11 @@ public class ArtistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getAlbumSongListClient() .getAlbumSongListClient()
.getStarred2() .getStarred2()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getStarred2() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getStarred2() != null) {
List<ArtistID3> artists = response.body().getStarred2().getArtists(); List<ArtistID3> artists = response.body().getSubsonicResponse().getStarred2().getArtists();
if (!random) { if (!random) {
getArtistInfo(artists, starredArtists); getArtistInfo(artists, starredArtists);
@ -51,7 +51,7 @@ public class ArtistRepository {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -65,13 +65,13 @@ public class ArtistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getArtists() .getArtists()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null) { if (response.isSuccessful() && response.body() != null) {
List<ArtistID3> artists = new ArrayList<>(); List<ArtistID3> artists = new ArrayList<>();
for (IndexID3 index : response.body().getArtists().getIndices()) { for (IndexID3 index : response.body().getSubsonicResponse().getArtists().getIndices()) {
artists.addAll(index.getArtists()); artists.addAll(index.getArtists());
} }
@ -85,7 +85,7 @@ public class ArtistRepository {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -104,16 +104,16 @@ public class ArtistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getArtist(artist.getId()) .getArtist(artist.getId())
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getArtist() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getArtist() != null) {
addToMutableLiveData(list, response.body().getArtist()); addToMutableLiveData(list, response.body().getSubsonicResponse().getArtist());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -126,16 +126,16 @@ public class ArtistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getArtist(id) .getArtist(id)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getArtist() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getArtist() != null) {
artist.setValue(response.body().getArtist()); artist.setValue(response.body().getSubsonicResponse().getArtist());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -152,16 +152,16 @@ public class ArtistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getArtistInfo2(id) .getArtistInfo2(id)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getArtistInfo2() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getArtistInfo2() != null) {
artistFullInfo.setValue(response.body().getArtistInfo2()); artistFullInfo.setValue(response.body().getSubsonicResponse().getArtistInfo2());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -173,14 +173,14 @@ public class ArtistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaAnnotationClient() .getMediaAnnotationClient()
.star(null, null, id) .star(null, null, id)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -190,14 +190,14 @@ public class ArtistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaAnnotationClient() .getMediaAnnotationClient()
.unstar(null, null, id) .unstar(null, null, id)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -207,14 +207,14 @@ public class ArtistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaAnnotationClient() .getMediaAnnotationClient()
.setRating(id, rating) .setRating(id, rating)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -226,16 +226,16 @@ public class ArtistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getArtist(id) .getArtist(id)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getArtist() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getArtist() != null) {
artist.setValue(response.body().getArtist()); artist.setValue(response.body().getSubsonicResponse().getArtist());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -249,16 +249,16 @@ public class ArtistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getSimilarSongs2(artist.getId(), count) .getSimilarSongs2(artist.getId(), count)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getSimilarSongs2() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getSimilarSongs2() != null) {
instantMix.setValue(response.body().getSimilarSongs2().getSongs()); instantMix.setValue(response.body().getSubsonicResponse().getSimilarSongs2().getSongs());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -272,11 +272,11 @@ public class ArtistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getArtist(artist.getId()) .getArtist(artist.getId())
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getArtist() != null && response.body().getArtist().getAlbums() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getArtist() != null && response.body().getSubsonicResponse().getArtist().getAlbums() != null) {
List<AlbumID3> albums = response.body().getArtist().getAlbums(); List<AlbumID3> albums = response.body().getSubsonicResponse().getArtist().getAlbums();
if (albums.size() > 0) { if (albums.size() > 0) {
AlbumRepository albumRepository = new AlbumRepository(App.getInstance()); AlbumRepository albumRepository = new AlbumRepository(App.getInstance());
@ -295,7 +295,7 @@ public class ArtistRepository {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -304,21 +304,21 @@ public class ArtistRepository {
} }
public MutableLiveData<List<Child>> getTopSongs(String artistName, int count) { public MutableLiveData<List<Child>> getTopSongs(String artistName, int count) {
MutableLiveData<List<Child>> topSongs = new MutableLiveData<>(); MutableLiveData<List<Child>> topSongs = new MutableLiveData<>(new ArrayList<>());
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getTopSongs(artistName, count) .getTopSongs(artistName, count)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getTopSongs() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getTopSongs() != null && response.body().getSubsonicResponse().getTopSongs().getSongs() != null) {
topSongs.setValue(response.body().getTopSongs().getSongs()); topSongs.setValue(response.body().getSubsonicResponse().getTopSongs().getSongs());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });

View file

@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.Genre; import com.cappielloantonio.play.subsonic.models.Genre;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
@ -31,11 +32,11 @@ public class GenreRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getGenres() .getGenres()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getGenres() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getGenres() != null) {
List<Genre> genreList = response.body().getGenres().getGenres(); List<Genre> genreList = response.body().getSubsonicResponse().getGenres().getGenres();
if (random) { if (random) {
Collections.shuffle(genreList); Collections.shuffle(genreList);
@ -50,7 +51,7 @@ public class GenreRepository {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });

View file

@ -10,9 +10,9 @@ import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.database.AppDatabase; import com.cappielloantonio.play.database.AppDatabase;
import com.cappielloantonio.play.database.dao.PlaylistDao; import com.cappielloantonio.play.database.dao.PlaylistDao;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.Child; import com.cappielloantonio.play.subsonic.models.Child;
import com.cappielloantonio.play.subsonic.models.Playlist; import com.cappielloantonio.play.subsonic.models.Playlist;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -34,16 +34,16 @@ public class PlaylistRepository {
} }
public MutableLiveData<List<Playlist>> getPlaylists(boolean random, int size) { public MutableLiveData<List<Playlist>> getPlaylists(boolean random, int size) {
MutableLiveData<List<Playlist>> listLivePlaylists = new MutableLiveData<>(); MutableLiveData<List<Playlist>> listLivePlaylists = new MutableLiveData<>(new ArrayList<>());
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getPlaylistClient() .getPlaylistClient()
.getPlaylists() .getPlaylists()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getPlaylists() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getPlaylists() != null && response.body().getSubsonicResponse().getPlaylists().getPlaylists() != null) {
List<Playlist> playlists = response.body().getPlaylists().getPlaylists(); List<Playlist> playlists = response.body().getSubsonicResponse().getPlaylists().getPlaylists();
if (random) { if (random) {
Collections.shuffle(playlists); Collections.shuffle(playlists);
@ -55,7 +55,7 @@ public class PlaylistRepository {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -68,17 +68,17 @@ public class PlaylistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getPlaylistClient() .getPlaylistClient()
.getPlaylist(id) .getPlaylist(id)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getPlaylist() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getPlaylist() != null) {
List<Child> songs = response.body().getPlaylist().getEntries(); List<Child> songs = response.body().getSubsonicResponse().getPlaylist().getEntries();
listLivePlaylistSongs.setValue(songs); listLivePlaylistSongs.setValue(songs);
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -89,14 +89,14 @@ public class PlaylistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getPlaylistClient() .getPlaylistClient()
.updatePlaylist(playlistId, null, true, songsId, null) .updatePlaylist(playlistId, null, true, songsId, null)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -106,14 +106,14 @@ public class PlaylistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getPlaylistClient() .getPlaylistClient()
.createPlaylist(playlistId, name, songsId) .createPlaylist(playlistId, name, songsId)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
Log.d("PLAYLIST", response.toString()); Log.d("PLAYLIST", response.toString());
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
Log.d("PLAYLIST", t.toString()); Log.d("PLAYLIST", t.toString());
} }
}); });
@ -123,14 +123,14 @@ public class PlaylistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getPlaylistClient() .getPlaylistClient()
.updatePlaylist(playlistId, name, isPublic, songIdToAdd, songIndexToRemove) .updatePlaylist(playlistId, name, isPublic, songIdToAdd, songIndexToRemove)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -140,14 +140,14 @@ public class PlaylistRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getPlaylistClient() .getPlaylistClient()
.deletePlaylist(playlistId) .deletePlaylist(playlistId)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });

View file

@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.PodcastChannel; import com.cappielloantonio.play.subsonic.models.PodcastChannel;
import com.cappielloantonio.play.subsonic.models.PodcastEpisode; import com.cappielloantonio.play.subsonic.models.PodcastEpisode;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
@ -32,16 +33,16 @@ public class PodcastRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getPodcastClient() .getPodcastClient()
.getPodcasts(includeEpisodes, channelId) .getPodcasts(includeEpisodes, channelId)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getPodcasts() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getPodcasts() != null) {
livePodcastChannel.setValue(response.body().getPodcasts().getChannels()); livePodcastChannel.setValue(response.body().getSubsonicResponse().getPodcasts().getChannels());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -55,16 +56,16 @@ public class PodcastRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getPodcastClient() .getPodcastClient()
.getNewestPodcasts(count) .getNewestPodcasts(count)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getNewestPodcasts() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getNewestPodcasts() != null) {
liveNewestPodcastEpisodes.setValue(response.body().getNewestPodcasts().getEpisodes()); liveNewestPodcastEpisodes.setValue(response.body().getSubsonicResponse().getNewestPodcasts().getEpisodes());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
Log.d(TAG, "onFailure()"); Log.d(TAG, "onFailure()");
} }
}); });
@ -76,14 +77,14 @@ public class PodcastRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getPodcastClient() .getPodcastClient()
.refreshPodcasts() .refreshPodcasts()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });

View file

@ -62,7 +62,12 @@ public class QueueRepository {
mediaList = getMediaThreadSafe.getMedia(); mediaList = getMediaThreadSafe.getMedia();
} }
mediaList.add(afterIndex, (Queue) media); Queue queueItem = new Queue(media);
mediaList.add(afterIndex, queueItem);
for (int i = 0; i < mediaList.size(); i++) {
mediaList.get(i).setTrackOrder(i);
}
Thread delete = new Thread(new DeleteAllThreadSafe(queueDao)); Thread delete = new Thread(new DeleteAllThreadSafe(queueDao));
delete.start(); delete.start();
@ -90,7 +95,12 @@ public class QueueRepository {
} }
for (int i = 0; i < toAdd.size(); i++) { for (int i = 0; i < toAdd.size(); i++) {
media.add(afterIndex + i, (Queue) toAdd.get(i)); Queue queueItem = new Queue(toAdd.get(i));
media.add(afterIndex + i, queueItem);
}
for (int i = 0; i < media.size(); i++) {
media.get(i).setTrackOrder(i);
} }
Thread delete = new Thread(new DeleteAllThreadSafe(queueDao)); Thread delete = new Thread(new DeleteAllThreadSafe(queueDao));

View file

@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.interfaces.ScanCallback; import com.cappielloantonio.play.interfaces.ScanCallback;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import retrofit2.Call; import retrofit2.Call;
@ -24,16 +25,16 @@ public class ScanRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaLibraryScanningClient() .getMediaLibraryScanningClient()
.startScan() .startScan()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull retrofit2.Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull retrofit2.Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getScanStatus() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getScanStatus() != null) {
callback.onSuccess(response.body().getScanStatus().isScanning(), response.body().getScanStatus().getCount()); callback.onSuccess(response.body().getSubsonicResponse().getScanStatus().isScanning(), response.body().getSubsonicResponse().getScanStatus().getCount());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
callback.onError(new Exception(t.getMessage())); callback.onError(new Exception(t.getMessage()));
} }
}); });
@ -43,16 +44,16 @@ public class ScanRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaLibraryScanningClient() .getMediaLibraryScanningClient()
.startScan() .startScan()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull retrofit2.Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull retrofit2.Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getScanStatus() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getScanStatus() != null) {
callback.onSuccess(response.body().getScanStatus().isScanning(), response.body().getScanStatus().getCount()); callback.onSuccess(response.body().getSubsonicResponse().getScanStatus().isScanning(), response.body().getSubsonicResponse().getScanStatus().getCount());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
callback.onError(new Exception(t.getMessage())); callback.onError(new Exception(t.getMessage()));
} }
}); });

View file

@ -9,6 +9,7 @@ import com.cappielloantonio.play.App;
import com.cappielloantonio.play.database.AppDatabase; import com.cappielloantonio.play.database.AppDatabase;
import com.cappielloantonio.play.database.dao.RecentSearchDao; import com.cappielloantonio.play.database.dao.RecentSearchDao;
import com.cappielloantonio.play.model.RecentSearch; import com.cappielloantonio.play.model.RecentSearch;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.AlbumID3; import com.cappielloantonio.play.subsonic.models.AlbumID3;
import com.cappielloantonio.play.subsonic.models.ArtistID3; import com.cappielloantonio.play.subsonic.models.ArtistID3;
import com.cappielloantonio.play.subsonic.models.Child; import com.cappielloantonio.play.subsonic.models.Child;
@ -39,15 +40,15 @@ public class SearchingRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getSearchingClient() .getSearchingClient()
.search3(query, 20, 0, 0) .search3(query, 20, 20, 20)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
result.setValue(response.body().getSearchResult3()); result.setValue(response.body().getSubsonicResponse().getSearchResult3());
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -61,22 +62,28 @@ public class SearchingRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getSearchingClient() .getSearchingClient()
.search3(query, 5, 5, 5) .search3(query, 5, 5, 5)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
List<String> newSuggestions = new ArrayList(); List<String> newSuggestions = new ArrayList();
if (response.isSuccessful() && response.body() != null) { if (response.isSuccessful() && response.body() != null) {
for (ArtistID3 artistID3 : response.body().getSearchResult3().getArtists()) { if(response.body().getSubsonicResponse().getSearchResult3().getArtists() != null) {
newSuggestions.add(artistID3.getName()); for (ArtistID3 artistID3 : response.body().getSubsonicResponse().getSearchResult3().getArtists()) {
newSuggestions.add(artistID3.getName());
}
} }
for (AlbumID3 albumID3 : response.body().getSearchResult3().getAlbums()) { if(response.body().getSubsonicResponse().getSearchResult3().getAlbums() != null) {
newSuggestions.add(albumID3.getName()); for (AlbumID3 albumID3 : response.body().getSubsonicResponse().getSearchResult3().getAlbums()) {
newSuggestions.add(albumID3.getName());
}
} }
for (Child song : response.body().getSearchResult3().getSongs()) { if(response.body().getSubsonicResponse().getSearchResult3().getSongs() != null) {
newSuggestions.add(song.getTitle()); for (Child song : response.body().getSubsonicResponse().getSearchResult3().getSongs()) {
newSuggestions.add(song.getTitle());
}
} }
LinkedHashSet<String> hashSet = new LinkedHashSet<>(newSuggestions); LinkedHashSet<String> hashSet = new LinkedHashSet<>(newSuggestions);
@ -87,7 +94,7 @@ public class SearchingRepository {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });

View file

@ -1,19 +1,23 @@
package com.cappielloantonio.play.repository; package com.cappielloantonio.play.repository;
import android.app.Application; import android.app.Application;
import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.Child; import com.cappielloantonio.play.subsonic.models.Child;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import kotlin.collections.EmptyList;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@ -28,28 +32,30 @@ public class SongRepository {
} }
public MutableLiveData<List<Child>> getStarredSongs(boolean random, int size) { public MutableLiveData<List<Child>> getStarredSongs(boolean random, int size) {
MutableLiveData<List<Child>> starredSongs = new MutableLiveData<>(); MutableLiveData<List<Child>> starredSongs = new MutableLiveData<>(Collections.EMPTY_LIST);
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getAlbumSongListClient() .getAlbumSongListClient()
.getStarred2() .getStarred2()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getStarred2() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getStarred2() != null) {
List<Child> songs = response.body().getStarred2().getSongs(); List<Child> songs = response.body().getSubsonicResponse().getStarred2().getSongs();
if (!random) { if (songs != null) {
starredSongs.setValue(songs); if (!random) {
} else { starredSongs.setValue(songs);
Collections.shuffle(songs); } else {
starredSongs.setValue(songs.subList(0, Math.min(size, songs.size()))); Collections.shuffle(songs);
starredSongs.setValue(songs.subList(0, Math.min(size, songs.size())));
}
} }
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -63,16 +69,16 @@ public class SongRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getSimilarSongs2(song.getId(), count) .getSimilarSongs2(song.getId(), count)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getSimilarSongs2() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getSimilarSongs2() != null) {
instantMix.setValue(response.body().getSimilarSongs2().getSongs()); instantMix.setValue(response.body().getSubsonicResponse().getSimilarSongs2().getSongs());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
instantMix.setValue(null); instantMix.setValue(null);
} }
}); });
@ -86,21 +92,21 @@ public class SongRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getAlbumSongListClient() .getAlbumSongListClient()
.getRandomSongs(number, fromYear, toYear) .getRandomSongs(number, fromYear, toYear)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
List<Child> songs = new ArrayList<>(); List<Child> songs = new ArrayList<>();
if (response.isSuccessful() && response.body() != null && response.body().getRandomSongs() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getRandomSongs() != null) {
songs.addAll(response.body().getRandomSongs().getSongs()); songs.addAll(response.body().getSubsonicResponse().getRandomSongs().getSongs());
} }
randomSongsSample.setValue(songs); randomSongsSample.setValue(songs);
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
Log.d(TAG, "onFailure: ");
} }
}); });
@ -111,14 +117,14 @@ public class SongRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaAnnotationClient() .getMediaAnnotationClient()
.scrobble(id) .scrobble(id)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -128,14 +134,14 @@ public class SongRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaAnnotationClient() .getMediaAnnotationClient()
.star(id, null, null) .star(id, null, null)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -145,14 +151,14 @@ public class SongRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaAnnotationClient() .getMediaAnnotationClient()
.unstar(id, null, null) .unstar(id, null, null)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -162,14 +168,14 @@ public class SongRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaAnnotationClient() .getMediaAnnotationClient()
.setRating(id, rating) .setRating(id, rating)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -181,11 +187,11 @@ public class SongRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getAlbumSongListClient() .getAlbumSongListClient()
.getSongsByGenre(id, 500, 0) .getSongsByGenre(id, 500, 0)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getSongsByGenre() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getSongsByGenre() != null) {
List<Child> newSongs = response.body().getSongsByGenre().getSongs(); List<Child> newSongs = response.body().getSubsonicResponse().getSongsByGenre().getSongs();
List<Child> songs = songsByGenre.getValue(); List<Child> songs = songsByGenre.getValue();
if (songs == null) songs = new ArrayList<>(); if (songs == null) songs = new ArrayList<>();
@ -200,7 +206,7 @@ public class SongRepository {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -215,20 +221,20 @@ public class SongRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getAlbumSongListClient() .getAlbumSongListClient()
.getSongsByGenre(id, 500, 0) .getSongsByGenre(id, 500, 0)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
List<Child> songs = new ArrayList<>(); List<Child> songs = new ArrayList<>();
if (response.isSuccessful() && response.body() != null && response.body().getSongsByGenre() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getSongsByGenre() != null) {
songs.addAll(response.body().getSongsByGenre().getSongs()); songs.addAll(response.body().getSubsonicResponse().getSongsByGenre().getSongs());
} }
songsByGenre.setValue(songs); songsByGenre.setValue(songs);
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });
@ -242,17 +248,17 @@ public class SongRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getBrowsingClient() .getBrowsingClient()
.getSong(id) .getSong(id)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null) { if (response.isSuccessful() && response.body() != null) {
song.setValue(response.body().getSong()); song.setValue(response.body().getSubsonicResponse().getSong());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
Log.d(TAG, "onFailure: ");
} }
}); });
@ -265,16 +271,16 @@ public class SongRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getMediaRetrievalClient() .getMediaRetrievalClient()
.getLyrics(song.getArtist(), song.getTitle()) .getLyrics(song.getArtist(), song.getTitle())
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getLyrics() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getLyrics() != null) {
lyrics.setValue(response.body().getLyrics().getContent()); lyrics.setValue(response.body().getSubsonicResponse().getLyrics().getContent());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });

View file

@ -7,6 +7,7 @@ import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.interfaces.SystemCallback; import com.cappielloantonio.play.interfaces.SystemCallback;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.ResponseStatus; import com.cappielloantonio.play.subsonic.models.ResponseStatus;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
@ -27,13 +28,13 @@ public class SystemRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getSystemClient() .getSystemClient()
.ping() .ping()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull retrofit2.Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull retrofit2.Response<ApiResponse> response) {
if (response.body() != null) { if (response.body() != null) {
if (response.body().getStatus().getValue().equals(ResponseStatus.FAILED)) { if (response.body().getSubsonicResponse().getStatus().equals(ResponseStatus.FAILED)) {
callback.onError(new Exception(response.body().getError().getCode().getValue() + " - " + response.body().getError().getMessage())); callback.onError(new Exception(response.body().getSubsonicResponse().getError().getCode().getValue() + " - " + response.body().getSubsonicResponse().getError().getMessage()));
} else if (response.body().getStatus().getValue().equals(ResponseStatus.OK)) { } else if (response.body().getSubsonicResponse().getStatus().equals(ResponseStatus.OK)) {
String password = response.raw().request().url().queryParameter("p"); String password = response.raw().request().url().queryParameter("p");
String token = response.raw().request().url().queryParameter("t"); String token = response.raw().request().url().queryParameter("t");
String salt = response.raw().request().url().queryParameter("s"); String salt = response.raw().request().url().queryParameter("s");
@ -47,7 +48,7 @@ public class SystemRepository {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
callback.onError(new Exception(t.getMessage())); callback.onError(new Exception(t.getMessage()));
} }
}); });
@ -59,16 +60,16 @@ public class SystemRepository {
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getSystemClient() .getSystemClient()
.ping() .ping()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null) { if (response.isSuccessful() && response.body() != null) {
pingResult.postValue(true); pingResult.postValue(true);
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
pingResult.postValue(false); pingResult.postValue(false);
} }
}); });

View file

@ -7,6 +7,7 @@ import androidx.media3.session.MediaBrowser;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.interfaces.MediaIndexCallback; import com.cappielloantonio.play.interfaces.MediaIndexCallback;
import com.cappielloantonio.play.model.Chronology;
import com.cappielloantonio.play.repository.ChronologyRepository; import com.cappielloantonio.play.repository.ChronologyRepository;
import com.cappielloantonio.play.repository.QueueRepository; import com.cappielloantonio.play.repository.QueueRepository;
import com.cappielloantonio.play.repository.SongRepository; import com.cappielloantonio.play.repository.SongRepository;
@ -306,7 +307,7 @@ public class MediaManager {
public static void saveChronology(MediaItem mediaItem) { public static void saveChronology(MediaItem mediaItem) {
if (mediaItem != null) if (mediaItem != null)
if (getQueueRepository().isMediaPlayingPlausible(mediaItem)) if (getQueueRepository().isMediaPlayingPlausible(mediaItem))
getChronologyRepository().insert(mediaItem.mediaMetadata.extras.getParcelable("child")); getChronologyRepository().insert(new Chronology(mediaItem));
} }
private static QueueRepository getQueueRepository() { private static QueueRepository getQueueRepository() {

View file

@ -234,7 +234,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) { override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
if (mediaItem == null) return if (mediaItem == null) return
if (mediaItem.mediaMetadata.extras!!.getString("mediaType") == Media.MEDIA_TYPE_MUSIC) { if (mediaItem.mediaMetadata.extras?.getString("type") == Media.MEDIA_TYPE_MUSIC) {
MediaManager.scrobble(mediaItem) MediaManager.scrobble(mediaItem)
MediaManager.saveChronology(mediaItem) MediaManager.saveChronology(mediaItem)
} }
@ -243,7 +243,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
} }
override fun onIsPlayingChanged(isPlaying: Boolean) { override fun onIsPlayingChanged(isPlaying: Boolean) {
if (isPlaying) { if (!isPlaying) {
MediaManager.setPlayingPausedTimestamp( MediaManager.setPlayingPausedTimestamp(
player.currentMediaItem, player.currentMediaItem,
player.currentPosition player.currentPosition

View file

@ -4,9 +4,10 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import com.cappielloantonio.play.subsonic.Subsonic; import com.cappielloantonio.play.subsonic.Subsonic;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import com.cappielloantonio.play.subsonic.utils.CacheUtil; import com.cappielloantonio.play.subsonic.utils.CacheUtil;
import com.tickaroo.tikxml.retrofit.TikXmlConverterFactory; import com.google.gson.GsonBuilder;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -15,6 +16,7 @@ import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class AlbumSongListClient { public class AlbumSongListClient {
private static final String TAG = "BrowsingClient"; private static final String TAG = "BrowsingClient";
@ -29,44 +31,44 @@ public class AlbumSongListClient {
Retrofit retrofit = new Retrofit.Builder() Retrofit retrofit = new Retrofit.Builder()
.baseUrl(subsonic.getUrl()) .baseUrl(subsonic.getUrl())
.addConverterFactory(TikXmlConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().create()))
.client(getOkHttpClient()) .client(getOkHttpClient())
.build(); .build();
this.albumSongListService = retrofit.create(AlbumSongListService.class); this.albumSongListService = retrofit.create(AlbumSongListService.class);
} }
public Call<SubsonicResponse> getAlbumList(String type, int size, int offset) { public Call<ApiResponse> getAlbumList(String type, int size, int offset) {
Log.d(TAG, "getAlbumList()"); Log.d(TAG, "getAlbumList()");
return albumSongListService.getAlbumList(subsonic.getParams(), type, size, offset); return albumSongListService.getAlbumList(subsonic.getParams(), type, size, offset);
} }
public Call<SubsonicResponse> getAlbumList2(String type, int size, int offset, Integer fromYear, Integer toYear) { public Call<ApiResponse> getAlbumList2(String type, int size, int offset, Integer fromYear, Integer toYear) {
Log.d(TAG, "getAlbumList2()"); Log.d(TAG, "getAlbumList2()");
return albumSongListService.getAlbumList2(subsonic.getParams(), type, size, offset, fromYear, toYear); return albumSongListService.getAlbumList2(subsonic.getParams(), type, size, offset, fromYear, toYear);
} }
public Call<SubsonicResponse> getRandomSongs(int size, Integer fromYear, Integer toYear) { public Call<ApiResponse> getRandomSongs(int size, Integer fromYear, Integer toYear) {
Log.d(TAG, "getRandomSongs()"); Log.d(TAG, "getRandomSongs()");
return albumSongListService.getRandomSongs(subsonic.getParams(), size, fromYear, toYear); return albumSongListService.getRandomSongs(subsonic.getParams(), size, fromYear, toYear);
} }
public Call<SubsonicResponse> getSongsByGenre(String genre, int count, int offset) { public Call<ApiResponse> getSongsByGenre(String genre, int count, int offset) {
Log.d(TAG, "getSongsByGenre()"); Log.d(TAG, "getSongsByGenre()");
return albumSongListService.getSongsByGenre(subsonic.getParams(), genre, count, offset); return albumSongListService.getSongsByGenre(subsonic.getParams(), genre, count, offset);
} }
public Call<SubsonicResponse> getNowPlaying() { public Call<ApiResponse> getNowPlaying() {
Log.d(TAG, "getNowPlaying()"); Log.d(TAG, "getNowPlaying()");
return albumSongListService.getNowPlaying(subsonic.getParams()); return albumSongListService.getNowPlaying(subsonic.getParams());
} }
public Call<SubsonicResponse> getStarred() { public Call<ApiResponse> getStarred() {
Log.d(TAG, "getStarred()"); Log.d(TAG, "getStarred()");
return albumSongListService.getStarred(subsonic.getParams()); return albumSongListService.getStarred(subsonic.getParams());
} }
public Call<SubsonicResponse> getStarred2() { public Call<ApiResponse> getStarred2() {
Log.d(TAG, "getStarred2()"); Log.d(TAG, "getStarred2()");
return albumSongListService.getStarred2(subsonic.getParams()); return albumSongListService.getStarred2(subsonic.getParams());
} }

View file

@ -1,5 +1,6 @@
package com.cappielloantonio.play.subsonic.api.albumsonglist; package com.cappielloantonio.play.subsonic.api.albumsonglist;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import java.util.Map; import java.util.Map;
@ -11,23 +12,23 @@ import retrofit2.http.QueryMap;
public interface AlbumSongListService { public interface AlbumSongListService {
@GET("getAlbumList") @GET("getAlbumList")
Call<SubsonicResponse> getAlbumList(@QueryMap Map<String, String> params, @Query("type") String type, @Query("size") int size, @Query("offset") int offset); Call<ApiResponse> getAlbumList(@QueryMap Map<String, String> params, @Query("type") String type, @Query("size") int size, @Query("offset") int offset);
@GET("getAlbumList2") @GET("getAlbumList2")
Call<SubsonicResponse> getAlbumList2(@QueryMap Map<String, String> params, @Query("type") String type, @Query("size") int size, @Query("offset") int offset, @Query("fromYear") Integer fromYear, @Query("toYear") Integer toYear); Call<ApiResponse> getAlbumList2(@QueryMap Map<String, String> params, @Query("type") String type, @Query("size") int size, @Query("offset") int offset, @Query("fromYear") Integer fromYear, @Query("toYear") Integer toYear);
@GET("getRandomSongs") @GET("getRandomSongs")
Call<SubsonicResponse> getRandomSongs(@QueryMap Map<String, String> params, @Query("size") int size, @Query("fromYear") Integer fromYear, @Query("toYear") Integer toYear); Call<ApiResponse> getRandomSongs(@QueryMap Map<String, String> params, @Query("size") int size, @Query("fromYear") Integer fromYear, @Query("toYear") Integer toYear);
@GET("getSongsByGenre") @GET("getSongsByGenre")
Call<SubsonicResponse> getSongsByGenre(@QueryMap Map<String, String> params, @Query("genre") String genre, @Query("count") int count, @Query("offset") int offset); Call<ApiResponse> getSongsByGenre(@QueryMap Map<String, String> params, @Query("genre") String genre, @Query("count") int count, @Query("offset") int offset);
@GET("getNowPlaying") @GET("getNowPlaying")
Call<SubsonicResponse> getNowPlaying(@QueryMap Map<String, String> params); Call<ApiResponse> getNowPlaying(@QueryMap Map<String, String> params);
@GET("getStarred") @GET("getStarred")
Call<SubsonicResponse> getStarred(@QueryMap Map<String, String> params); Call<ApiResponse> getStarred(@QueryMap Map<String, String> params);
@GET("getStarred2") @GET("getStarred2")
Call<SubsonicResponse> getStarred2(@QueryMap Map<String, String> params); Call<ApiResponse> getStarred2(@QueryMap Map<String, String> params);
} }

View file

@ -4,9 +4,10 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import com.cappielloantonio.play.subsonic.Subsonic; import com.cappielloantonio.play.subsonic.Subsonic;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import com.cappielloantonio.play.subsonic.utils.CacheUtil; import com.cappielloantonio.play.subsonic.utils.CacheUtil;
import com.tickaroo.tikxml.retrofit.TikXmlConverterFactory; import com.google.gson.GsonBuilder;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -15,6 +16,7 @@ import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class BrowsingClient { public class BrowsingClient {
private static final String TAG = "BrowsingClient"; private static final String TAG = "BrowsingClient";
@ -29,94 +31,94 @@ public class BrowsingClient {
Retrofit retrofit = new Retrofit.Builder() Retrofit retrofit = new Retrofit.Builder()
.baseUrl(subsonic.getUrl()) .baseUrl(subsonic.getUrl())
.addConverterFactory(TikXmlConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().create()))
.client(getOkHttpClient()) .client(getOkHttpClient())
.build(); .build();
this.browsingService = retrofit.create(BrowsingService.class); this.browsingService = retrofit.create(BrowsingService.class);
} }
public Call<SubsonicResponse> getMusicFolders() { public Call<ApiResponse> getMusicFolders() {
Log.d(TAG, "getMusicFolders()"); Log.d(TAG, "getMusicFolders()");
return browsingService.getMusicFolders(subsonic.getParams()); return browsingService.getMusicFolders(subsonic.getParams());
} }
public Call<SubsonicResponse> getIndexes() { public Call<ApiResponse> getIndexes() {
Log.d(TAG, "getIndexes()"); Log.d(TAG, "getIndexes()");
return browsingService.getIndexes(subsonic.getParams()); return browsingService.getIndexes(subsonic.getParams());
} }
public Call<SubsonicResponse> getMusicDirectory(String id) { public Call<ApiResponse> getMusicDirectory(String id) {
Log.d(TAG, "getMusicDirectory()"); Log.d(TAG, "getMusicDirectory()");
return browsingService.getMusicDirectory(subsonic.getParams(), id); return browsingService.getMusicDirectory(subsonic.getParams(), id);
} }
public Call<SubsonicResponse> getGenres() { public Call<ApiResponse> getGenres() {
Log.d(TAG, "getGenres()"); Log.d(TAG, "getGenres()");
return browsingService.getGenres(subsonic.getParams()); return browsingService.getGenres(subsonic.getParams());
} }
public Call<SubsonicResponse> getArtists() { public Call<ApiResponse> getArtists() {
Log.d(TAG, "getArtists()"); Log.d(TAG, "getArtists()");
return browsingService.getArtists(subsonic.getParams()); return browsingService.getArtists(subsonic.getParams());
} }
public Call<SubsonicResponse> getArtist(String id) { public Call<ApiResponse> getArtist(String id) {
Log.d(TAG, "getArtist()"); Log.d(TAG, "getArtist()");
return browsingService.getArtist(subsonic.getParams(), id); return browsingService.getArtist(subsonic.getParams(), id);
} }
public Call<SubsonicResponse> getAlbum(String id) { public Call<ApiResponse> getAlbum(String id) {
Log.d(TAG, "getAlbum()"); Log.d(TAG, "getAlbum()");
return browsingService.getAlbum(subsonic.getParams(), id); return browsingService.getAlbum(subsonic.getParams(), id);
} }
public Call<SubsonicResponse> getSong(String id) { public Call<ApiResponse> getSong(String id) {
Log.d(TAG, "getSong()"); Log.d(TAG, "getSong()");
return browsingService.getSong(subsonic.getParams(), id); return browsingService.getSong(subsonic.getParams(), id);
} }
public Call<SubsonicResponse> getVideos() { public Call<ApiResponse> getVideos() {
Log.d(TAG, "getVideos()"); Log.d(TAG, "getVideos()");
return browsingService.getVideos(subsonic.getParams()); return browsingService.getVideos(subsonic.getParams());
} }
public Call<SubsonicResponse> getVideoInfo(String id) { public Call<ApiResponse> getVideoInfo(String id) {
Log.d(TAG, "getVideoInfo()"); Log.d(TAG, "getVideoInfo()");
return browsingService.getVideoInfo(subsonic.getParams(), id); return browsingService.getVideoInfo(subsonic.getParams(), id);
} }
public Call<SubsonicResponse> getArtistInfo(String id) { public Call<ApiResponse> getArtistInfo(String id) {
Log.d(TAG, "getArtistInfo()"); Log.d(TAG, "getArtistInfo()");
return browsingService.getArtistInfo(subsonic.getParams(), id); return browsingService.getArtistInfo(subsonic.getParams(), id);
} }
public Call<SubsonicResponse> getArtistInfo2(String id) { public Call<ApiResponse> getArtistInfo2(String id) {
Log.d(TAG, "getArtistInfo2()"); Log.d(TAG, "getArtistInfo2()");
return browsingService.getArtistInfo2(subsonic.getParams(), id); return browsingService.getArtistInfo2(subsonic.getParams(), id);
} }
public Call<SubsonicResponse> getAlbumInfo(String id) { public Call<ApiResponse> getAlbumInfo(String id) {
Log.d(TAG, "getAlbumInfo()"); Log.d(TAG, "getAlbumInfo()");
return browsingService.getAlbumInfo(subsonic.getParams(), id); return browsingService.getAlbumInfo(subsonic.getParams(), id);
} }
public Call<SubsonicResponse> getAlbumInfo2(String id) { public Call<ApiResponse> getAlbumInfo2(String id) {
Log.d(TAG, "getAlbumInfo2()"); Log.d(TAG, "getAlbumInfo2()");
return browsingService.getAlbumInfo2(subsonic.getParams(), id); return browsingService.getAlbumInfo2(subsonic.getParams(), id);
} }
public Call<SubsonicResponse> getSimilarSongs(String id, int count) { public Call<ApiResponse> getSimilarSongs(String id, int count) {
Log.d(TAG, "getSimilarSongs()"); Log.d(TAG, "getSimilarSongs()");
return browsingService.getSimilarSongs(subsonic.getParams(), id, count); return browsingService.getSimilarSongs(subsonic.getParams(), id, count);
} }
public Call<SubsonicResponse> getSimilarSongs2(String id, int limit) { public Call<ApiResponse> getSimilarSongs2(String id, int limit) {
Log.d(TAG, "getSimilarSongs2()"); Log.d(TAG, "getSimilarSongs2()");
return browsingService.getSimilarSongs2(subsonic.getParams(), id, limit); return browsingService.getSimilarSongs2(subsonic.getParams(), id, limit);
} }
public Call<SubsonicResponse> getTopSongs(String artist, int count) { public Call<ApiResponse> getTopSongs(String artist, int count) {
Log.d(TAG, "getTopSongs()"); Log.d(TAG, "getTopSongs()");
return browsingService.getTopSongs(subsonic.getParams(), artist, count); return browsingService.getTopSongs(subsonic.getParams(), artist, count);
} }

View file

@ -1,5 +1,6 @@
package com.cappielloantonio.play.subsonic.api.browsing; package com.cappielloantonio.play.subsonic.api.browsing;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import java.util.Map; import java.util.Map;
@ -11,53 +12,53 @@ import retrofit2.http.QueryMap;
public interface BrowsingService { public interface BrowsingService {
@GET("getMusicFolders") @GET("getMusicFolders")
Call<SubsonicResponse> getMusicFolders(@QueryMap Map<String, String> params); Call<ApiResponse> getMusicFolders(@QueryMap Map<String, String> params);
@GET("getIndexes") @GET("getIndexes")
Call<SubsonicResponse> getIndexes(@QueryMap Map<String, String> params); Call<ApiResponse> getIndexes(@QueryMap Map<String, String> params);
@GET("getMusicDirectory") @GET("getMusicDirectory")
Call<SubsonicResponse> getMusicDirectory(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> getMusicDirectory(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("getGenres") @GET("getGenres")
Call<SubsonicResponse> getGenres(@QueryMap Map<String, String> params); Call<ApiResponse> getGenres(@QueryMap Map<String, String> params);
@GET("getArtists") @GET("getArtists")
Call<SubsonicResponse> getArtists(@QueryMap Map<String, String> params); Call<ApiResponse> getArtists(@QueryMap Map<String, String> params);
@GET("getArtist") @GET("getArtist")
Call<SubsonicResponse> getArtist(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> getArtist(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("getAlbum") @GET("getAlbum")
Call<SubsonicResponse> getAlbum(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> getAlbum(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("getSong") @GET("getSong")
Call<SubsonicResponse> getSong(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> getSong(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("getVideos") @GET("getVideos")
Call<SubsonicResponse> getVideos(@QueryMap Map<String, String> params); Call<ApiResponse> getVideos(@QueryMap Map<String, String> params);
@GET("getVideoInfo") @GET("getVideoInfo")
Call<SubsonicResponse> getVideoInfo(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> getVideoInfo(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("getArtistInfo") @GET("getArtistInfo")
Call<SubsonicResponse> getArtistInfo(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> getArtistInfo(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("getArtistInfo2") @GET("getArtistInfo2")
Call<SubsonicResponse> getArtistInfo2(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> getArtistInfo2(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("getAlbumInfo") @GET("getAlbumInfo")
Call<SubsonicResponse> getAlbumInfo(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> getAlbumInfo(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("getAlbumInfo2") @GET("getAlbumInfo2")
Call<SubsonicResponse> getAlbumInfo2(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> getAlbumInfo2(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("getSimilarSongs") @GET("getSimilarSongs")
Call<SubsonicResponse> getSimilarSongs(@QueryMap Map<String, String> params, @Query("id") String id, @Query("count") int count); Call<ApiResponse> getSimilarSongs(@QueryMap Map<String, String> params, @Query("id") String id, @Query("count") int count);
@GET("getSimilarSongs2") @GET("getSimilarSongs2")
Call<SubsonicResponse> getSimilarSongs2(@QueryMap Map<String, String> params, @Query("id") String id, @Query("count") int count); Call<ApiResponse> getSimilarSongs2(@QueryMap Map<String, String> params, @Query("id") String id, @Query("count") int count);
@GET("getTopSongs") @GET("getTopSongs")
Call<SubsonicResponse> getTopSongs(@QueryMap Map<String, String> params, @Query("artist") String artist, @Query("count") int count); Call<ApiResponse> getTopSongs(@QueryMap Map<String, String> params, @Query("artist") String artist, @Query("count") int count);
} }

View file

@ -4,9 +4,10 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import com.cappielloantonio.play.subsonic.Subsonic; import com.cappielloantonio.play.subsonic.Subsonic;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import com.cappielloantonio.play.subsonic.utils.CacheUtil; import com.cappielloantonio.play.subsonic.utils.CacheUtil;
import com.tickaroo.tikxml.retrofit.TikXmlConverterFactory; import com.google.gson.GsonBuilder;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -15,6 +16,7 @@ import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MediaAnnotationClient { public class MediaAnnotationClient {
private static final String TAG = "BrowsingClient"; private static final String TAG = "BrowsingClient";
@ -29,29 +31,29 @@ public class MediaAnnotationClient {
Retrofit retrofit = new Retrofit.Builder() Retrofit retrofit = new Retrofit.Builder()
.baseUrl(subsonic.getUrl()) .baseUrl(subsonic.getUrl())
.addConverterFactory(TikXmlConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().create()))
.client(getOkHttpClient()) .client(getOkHttpClient())
.build(); .build();
this.mediaAnnotationService = retrofit.create(MediaAnnotationService.class); this.mediaAnnotationService = retrofit.create(MediaAnnotationService.class);
} }
public Call<SubsonicResponse> star(String id, String albumId, String artistId) { public Call<ApiResponse> star(String id, String albumId, String artistId) {
Log.d(TAG, "star()"); Log.d(TAG, "star()");
return mediaAnnotationService.star(subsonic.getParams(), id, albumId, artistId); return mediaAnnotationService.star(subsonic.getParams(), id, albumId, artistId);
} }
public Call<SubsonicResponse> unstar(String id, String albumId, String artistId) { public Call<ApiResponse> unstar(String id, String albumId, String artistId) {
Log.d(TAG, "unstar()"); Log.d(TAG, "unstar()");
return mediaAnnotationService.unstar(subsonic.getParams(), id, albumId, artistId); return mediaAnnotationService.unstar(subsonic.getParams(), id, albumId, artistId);
} }
public Call<SubsonicResponse> setRating(String id, int rating) { public Call<ApiResponse> setRating(String id, int rating) {
Log.d(TAG, "setRating()"); Log.d(TAG, "setRating()");
return mediaAnnotationService.setRating(subsonic.getParams(), id, rating); return mediaAnnotationService.setRating(subsonic.getParams(), id, rating);
} }
public Call<SubsonicResponse> scrobble(String id) { public Call<ApiResponse> scrobble(String id) {
Log.d(TAG, "scrobble()"); Log.d(TAG, "scrobble()");
return mediaAnnotationService.scrobble(subsonic.getParams(), id); return mediaAnnotationService.scrobble(subsonic.getParams(), id);
} }

View file

@ -1,5 +1,6 @@
package com.cappielloantonio.play.subsonic.api.mediaannotation; package com.cappielloantonio.play.subsonic.api.mediaannotation;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import java.util.Map; import java.util.Map;
@ -11,14 +12,14 @@ import retrofit2.http.QueryMap;
public interface MediaAnnotationService { public interface MediaAnnotationService {
@GET("star") @GET("star")
Call<SubsonicResponse> star(@QueryMap Map<String, String> params, @Query("id") String id, @Query("albumId") String albumId, @Query("artistId") String artistId); Call<ApiResponse> star(@QueryMap Map<String, String> params, @Query("id") String id, @Query("albumId") String albumId, @Query("artistId") String artistId);
@GET("unstar") @GET("unstar")
Call<SubsonicResponse> unstar(@QueryMap Map<String, String> params, @Query("id") String id, @Query("albumId") String albumId, @Query("artistId") String artistId); Call<ApiResponse> unstar(@QueryMap Map<String, String> params, @Query("id") String id, @Query("albumId") String albumId, @Query("artistId") String artistId);
@GET("setRating") @GET("setRating")
Call<SubsonicResponse> setRating(@QueryMap Map<String, String> params, @Query("id") String id, @Query("rating") int rating); Call<ApiResponse> setRating(@QueryMap Map<String, String> params, @Query("id") String id, @Query("rating") int rating);
@GET("scrobble") @GET("scrobble")
Call<SubsonicResponse> scrobble(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> scrobble(@QueryMap Map<String, String> params, @Query("id") String id);
} }

View file

@ -4,9 +4,10 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import com.cappielloantonio.play.subsonic.Subsonic; import com.cappielloantonio.play.subsonic.Subsonic;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import com.cappielloantonio.play.subsonic.utils.CacheUtil; import com.cappielloantonio.play.subsonic.utils.CacheUtil;
import com.tickaroo.tikxml.retrofit.TikXmlConverterFactory; import com.google.gson.GsonBuilder;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -15,6 +16,7 @@ import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MediaLibraryScanningClient { public class MediaLibraryScanningClient {
private static final String TAG = "SystemClient"; private static final String TAG = "SystemClient";
@ -29,19 +31,19 @@ public class MediaLibraryScanningClient {
Retrofit retrofit = new Retrofit.Builder() Retrofit retrofit = new Retrofit.Builder()
.baseUrl(subsonic.getUrl()) .baseUrl(subsonic.getUrl())
.addConverterFactory(TikXmlConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().create()))
.client(getOkHttpClient()) .client(getOkHttpClient())
.build(); .build();
this.mediaLibraryScanningService = retrofit.create(MediaLibraryScanningService.class); this.mediaLibraryScanningService = retrofit.create(MediaLibraryScanningService.class);
} }
public Call<SubsonicResponse> startScan() { public Call<ApiResponse> startScan() {
Log.d(TAG, "startScan()"); Log.d(TAG, "startScan()");
return mediaLibraryScanningService.startScan(subsonic.getParams()); return mediaLibraryScanningService.startScan(subsonic.getParams());
} }
public Call<SubsonicResponse> getScanStatus() { public Call<ApiResponse> getScanStatus() {
Log.d(TAG, "getScanStatus()"); Log.d(TAG, "getScanStatus()");
return mediaLibraryScanningService.getScanStatus(subsonic.getParams()); return mediaLibraryScanningService.getScanStatus(subsonic.getParams());
} }

View file

@ -1,6 +1,6 @@
package com.cappielloantonio.play.subsonic.api.medialibraryscanning; package com.cappielloantonio.play.subsonic.api.medialibraryscanning;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.base.ApiResponse;
import java.util.Map; import java.util.Map;
@ -10,8 +10,8 @@ import retrofit2.http.QueryMap;
public interface MediaLibraryScanningService { public interface MediaLibraryScanningService {
@GET("startScan") @GET("startScan")
Call<SubsonicResponse> startScan(@QueryMap Map<String, String> params); Call<ApiResponse> startScan(@QueryMap Map<String, String> params);
@GET("getScanStatus") @GET("getScanStatus")
Call<SubsonicResponse> getScanStatus(@QueryMap Map<String, String> params); Call<ApiResponse> getScanStatus(@QueryMap Map<String, String> params);
} }

View file

@ -4,9 +4,10 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import com.cappielloantonio.play.subsonic.Subsonic; import com.cappielloantonio.play.subsonic.Subsonic;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import com.cappielloantonio.play.subsonic.utils.CacheUtil; import com.cappielloantonio.play.subsonic.utils.CacheUtil;
import com.tickaroo.tikxml.retrofit.TikXmlConverterFactory; import com.google.gson.GsonBuilder;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -15,6 +16,7 @@ import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MediaRetrievalClient { public class MediaRetrievalClient {
private static final String TAG = "BrowsingClient"; private static final String TAG = "BrowsingClient";
@ -29,24 +31,24 @@ public class MediaRetrievalClient {
Retrofit retrofit = new Retrofit.Builder() Retrofit retrofit = new Retrofit.Builder()
.baseUrl(subsonic.getUrl()) .baseUrl(subsonic.getUrl())
.addConverterFactory(TikXmlConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().create()))
.client(getOkHttpClient()) .client(getOkHttpClient())
.build(); .build();
this.mediaRetrievalService = retrofit.create(MediaRetrievalService.class); this.mediaRetrievalService = retrofit.create(MediaRetrievalService.class);
} }
public Call<SubsonicResponse> stream(String id, Integer maxBitRate, String format) { public Call<ApiResponse> stream(String id, Integer maxBitRate, String format) {
Log.d(TAG, "stream()"); Log.d(TAG, "stream()");
return mediaRetrievalService.stream(subsonic.getParams(), id, maxBitRate, format); return mediaRetrievalService.stream(subsonic.getParams(), id, maxBitRate, format);
} }
public Call<SubsonicResponse> download(String id) { public Call<ApiResponse> download(String id) {
Log.d(TAG, "download()"); Log.d(TAG, "download()");
return mediaRetrievalService.download(subsonic.getParams(), id); return mediaRetrievalService.download(subsonic.getParams(), id);
} }
public Call<SubsonicResponse> getLyrics(String artist, String title) { public Call<ApiResponse> getLyrics(String artist, String title) {
Log.d(TAG, "getLyrics()"); Log.d(TAG, "getLyrics()");
return mediaRetrievalService.getLyrics(subsonic.getParams(), artist, title); return mediaRetrievalService.getLyrics(subsonic.getParams(), artist, title);
} }

View file

@ -1,5 +1,6 @@
package com.cappielloantonio.play.subsonic.api.mediaretrieval; package com.cappielloantonio.play.subsonic.api.mediaretrieval;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import java.util.Map; import java.util.Map;
@ -11,11 +12,11 @@ import retrofit2.http.QueryMap;
public interface MediaRetrievalService { public interface MediaRetrievalService {
@GET("stream") @GET("stream")
Call<SubsonicResponse> stream(@QueryMap Map<String, String> params, @Query("id") String id, @Query("maxBitRate") Integer maxBitRate, @Query("format") String format); Call<ApiResponse> stream(@QueryMap Map<String, String> params, @Query("id") String id, @Query("maxBitRate") Integer maxBitRate, @Query("format") String format);
@GET("download") @GET("download")
Call<SubsonicResponse> download(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> download(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("getLyrics") @GET("getLyrics")
Call<SubsonicResponse> getLyrics(@QueryMap Map<String, String> params, @Query("artist") String artist, @Query("title") String title); Call<ApiResponse> getLyrics(@QueryMap Map<String, String> params, @Query("artist") String artist, @Query("title") String title);
} }

View file

@ -4,9 +4,10 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import com.cappielloantonio.play.subsonic.Subsonic; import com.cappielloantonio.play.subsonic.Subsonic;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import com.cappielloantonio.play.subsonic.utils.CacheUtil; import com.cappielloantonio.play.subsonic.utils.CacheUtil;
import com.tickaroo.tikxml.retrofit.TikXmlConverterFactory; import com.google.gson.GsonBuilder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -16,6 +17,7 @@ import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class PlaylistClient { public class PlaylistClient {
private static final String TAG = "BrowsingClient"; private static final String TAG = "BrowsingClient";
@ -30,34 +32,34 @@ public class PlaylistClient {
Retrofit retrofit = new Retrofit.Builder() Retrofit retrofit = new Retrofit.Builder()
.baseUrl(subsonic.getUrl()) .baseUrl(subsonic.getUrl())
.addConverterFactory(TikXmlConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().create()))
.client(getOkHttpClient()) .client(getOkHttpClient())
.build(); .build();
this.playlistService = retrofit.create(PlaylistService.class); this.playlistService = retrofit.create(PlaylistService.class);
} }
public Call<SubsonicResponse> getPlaylists() { public Call<ApiResponse> getPlaylists() {
Log.d(TAG, "getPlaylists()"); Log.d(TAG, "getPlaylists()");
return playlistService.getPlaylists(subsonic.getParams()); return playlistService.getPlaylists(subsonic.getParams());
} }
public Call<SubsonicResponse> getPlaylist(String id) { public Call<ApiResponse> getPlaylist(String id) {
Log.d(TAG, "getPlaylist()"); Log.d(TAG, "getPlaylist()");
return playlistService.getPlaylist(subsonic.getParams(), id); return playlistService.getPlaylist(subsonic.getParams(), id);
} }
public Call<SubsonicResponse> createPlaylist(String playlistId, String name, ArrayList<String> songsId) { public Call<ApiResponse> createPlaylist(String playlistId, String name, ArrayList<String> songsId) {
Log.d(TAG, "createPlaylist()"); Log.d(TAG, "createPlaylist()");
return playlistService.createPlaylist(subsonic.getParams(), playlistId, name, songsId); return playlistService.createPlaylist(subsonic.getParams(), playlistId, name, songsId);
} }
public Call<SubsonicResponse> updatePlaylist(String playlistId, String name, boolean isPublic, ArrayList<String> songIdToAdd, ArrayList<Integer> songIndexToRemove) { public Call<ApiResponse> updatePlaylist(String playlistId, String name, boolean isPublic, ArrayList<String> songIdToAdd, ArrayList<Integer> songIndexToRemove) {
Log.d(TAG, "updatePlaylist()"); Log.d(TAG, "updatePlaylist()");
return playlistService.updatePlaylist(subsonic.getParams(), playlistId, name, isPublic, songIdToAdd, songIndexToRemove); return playlistService.updatePlaylist(subsonic.getParams(), playlistId, name, isPublic, songIdToAdd, songIndexToRemove);
} }
public Call<SubsonicResponse> deletePlaylist(String id) { public Call<ApiResponse> deletePlaylist(String id) {
Log.d(TAG, "deletePlaylist()"); Log.d(TAG, "deletePlaylist()");
return playlistService.deletePlaylist(subsonic.getParams(), id); return playlistService.deletePlaylist(subsonic.getParams(), id);
} }

View file

@ -1,5 +1,6 @@
package com.cappielloantonio.play.subsonic.api.playlist; package com.cappielloantonio.play.subsonic.api.playlist;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import java.util.ArrayList; import java.util.ArrayList;
@ -12,17 +13,17 @@ import retrofit2.http.QueryMap;
public interface PlaylistService { public interface PlaylistService {
@GET("getPlaylists") @GET("getPlaylists")
Call<SubsonicResponse> getPlaylists(@QueryMap Map<String, String> params); Call<ApiResponse> getPlaylists(@QueryMap Map<String, String> params);
@GET("getPlaylist") @GET("getPlaylist")
Call<SubsonicResponse> getPlaylist(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> getPlaylist(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("createPlaylist") @GET("createPlaylist")
Call<SubsonicResponse> createPlaylist(@QueryMap Map<String, String> params, @Query("playlistId") String playlistId, @Query("name") String name, @Query("songId") ArrayList<String> songsId); Call<ApiResponse> createPlaylist(@QueryMap Map<String, String> params, @Query("playlistId") String playlistId, @Query("name") String name, @Query("songId") ArrayList<String> songsId);
@GET("updatePlaylist") @GET("updatePlaylist")
Call<SubsonicResponse> updatePlaylist(@QueryMap Map<String, String> params, @Query("playlistId") String playlistId, @Query("name") String name, @Query("public") boolean isPublic, @Query("songIdToAdd") ArrayList<String> songIdToAdd, @Query("songIndexToRemove") ArrayList<Integer> songIndexToRemove); Call<ApiResponse> updatePlaylist(@QueryMap Map<String, String> params, @Query("playlistId") String playlistId, @Query("name") String name, @Query("public") boolean isPublic, @Query("songIdToAdd") ArrayList<String> songIdToAdd, @Query("songIndexToRemove") ArrayList<Integer> songIndexToRemove);
@GET("deletePlaylist") @GET("deletePlaylist")
Call<SubsonicResponse> deletePlaylist(@QueryMap Map<String, String> params, @Query("id") String id); Call<ApiResponse> deletePlaylist(@QueryMap Map<String, String> params, @Query("id") String id);
} }

View file

@ -4,9 +4,10 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import com.cappielloantonio.play.subsonic.Subsonic; import com.cappielloantonio.play.subsonic.Subsonic;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import com.cappielloantonio.play.subsonic.utils.CacheUtil; import com.cappielloantonio.play.subsonic.utils.CacheUtil;
import com.tickaroo.tikxml.retrofit.TikXmlConverterFactory; import com.google.gson.GsonBuilder;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -15,6 +16,7 @@ import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class PodcastClient { public class PodcastClient {
private static final String TAG = "SystemClient"; private static final String TAG = "SystemClient";
@ -29,27 +31,28 @@ public class PodcastClient {
Retrofit retrofit = new Retrofit.Builder() Retrofit retrofit = new Retrofit.Builder()
.baseUrl(subsonic.getUrl()) .baseUrl(subsonic.getUrl())
.addConverterFactory(TikXmlConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().create()))
.client(getOkHttpClient()) .client(getOkHttpClient())
.build(); .build();
this.podcastService = retrofit.create(PodcastService.class); this.podcastService = retrofit.create(PodcastService.class);
} }
public Call<SubsonicResponse> getPodcasts(boolean includeEpisodes, String channelId) { public Call<ApiResponse> getPodcasts(boolean includeEpisodes, String channelId) {
Log.d(TAG, "getPodcasts()"); Log.d(TAG, "getPodcasts()");
return podcastService.getPodcasts(subsonic.getParams(), includeEpisodes, channelId); return podcastService.getPodcasts(subsonic.getParams(), includeEpisodes, channelId);
} }
public Call<SubsonicResponse> getNewestPodcasts(int count) { public Call<ApiResponse> getNewestPodcasts(int count) {
Log.d(TAG, "getNewestPodcasts()"); Log.d(TAG, "getNewestPodcasts()");
return podcastService.getNewestPodcasts(subsonic.getParams(), count); return podcastService.getNewestPodcasts(subsonic.getParams(), count);
} }
public Call<SubsonicResponse> refreshPodcasts() { public Call<ApiResponse> refreshPodcasts() {
Log.d(TAG, "refreshPodcasts()"); Log.d(TAG, "refreshPodcasts()");
return podcastService.refreshPodcasts(subsonic.getParams()); return podcastService.refreshPodcasts(subsonic.getParams());
} }
private OkHttpClient getOkHttpClient() { private OkHttpClient getOkHttpClient() {
CacheUtil cacheUtil = new CacheUtil(context, 60, 60 * 60 * 24 * 30); CacheUtil cacheUtil = new CacheUtil(context, 60, 60 * 60 * 24 * 30);

View file

@ -1,5 +1,6 @@
package com.cappielloantonio.play.subsonic.api.podcast; package com.cappielloantonio.play.subsonic.api.podcast;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import java.util.Map; import java.util.Map;
@ -11,11 +12,11 @@ import retrofit2.http.QueryMap;
public interface PodcastService { public interface PodcastService {
@GET("getPodcasts") @GET("getPodcasts")
Call<SubsonicResponse> getPodcasts(@QueryMap Map<String, String> params, @Query("includeEpisodes") boolean includeEpisodes, @Query("id") String id); Call<ApiResponse> getPodcasts(@QueryMap Map<String, String> params, @Query("includeEpisodes") boolean includeEpisodes, @Query("id") String id);
@GET("getNewestPodcasts") @GET("getNewestPodcasts")
Call<SubsonicResponse> getNewestPodcasts(@QueryMap Map<String, String> params, @Query("count") int count); Call<ApiResponse> getNewestPodcasts(@QueryMap Map<String, String> params, @Query("count") int count);
@GET("refreshPodcasts") @GET("refreshPodcasts")
Call<SubsonicResponse> refreshPodcasts(@QueryMap Map<String, String> params); Call<ApiResponse> refreshPodcasts(@QueryMap Map<String, String> params);
} }

View file

@ -4,9 +4,10 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import com.cappielloantonio.play.subsonic.Subsonic; import com.cappielloantonio.play.subsonic.Subsonic;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import com.cappielloantonio.play.subsonic.utils.CacheUtil; import com.cappielloantonio.play.subsonic.utils.CacheUtil;
import com.tickaroo.tikxml.retrofit.TikXmlConverterFactory; import com.google.gson.GsonBuilder;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -15,6 +16,7 @@ import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class SearchingClient { public class SearchingClient {
private static final String TAG = "BrowsingClient"; private static final String TAG = "BrowsingClient";
@ -29,19 +31,19 @@ public class SearchingClient {
Retrofit retrofit = new Retrofit.Builder() Retrofit retrofit = new Retrofit.Builder()
.baseUrl(subsonic.getUrl()) .baseUrl(subsonic.getUrl())
.addConverterFactory(TikXmlConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().create()))
.client(getOkHttpClient()) .client(getOkHttpClient())
.build(); .build();
this.searchingService = retrofit.create(SearchingService.class); this.searchingService = retrofit.create(SearchingService.class);
} }
public Call<SubsonicResponse> search2(String query, int songCount, int albumCount, int artistCount) { public Call<ApiResponse> search2(String query, int songCount, int albumCount, int artistCount) {
Log.d(TAG, "search2()"); Log.d(TAG, "search2()");
return searchingService.search2(subsonic.getParams(), query, songCount, albumCount, artistCount); return searchingService.search2(subsonic.getParams(), query, songCount, albumCount, artistCount);
} }
public Call<SubsonicResponse> search3(String query, int songCount, int albumCount, int artistCount) { public Call<ApiResponse> search3(String query, int songCount, int albumCount, int artistCount) {
Log.d(TAG, "search3()"); Log.d(TAG, "search3()");
return searchingService.search3(subsonic.getParams(), query, songCount, albumCount, artistCount); return searchingService.search3(subsonic.getParams(), query, songCount, albumCount, artistCount);
} }

View file

@ -1,5 +1,6 @@
package com.cappielloantonio.play.subsonic.api.searching; package com.cappielloantonio.play.subsonic.api.searching;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import java.util.Map; import java.util.Map;
@ -11,8 +12,8 @@ import retrofit2.http.QueryMap;
public interface SearchingService { public interface SearchingService {
@GET("search2") @GET("search2")
Call<SubsonicResponse> search2(@QueryMap Map<String, String> params, @Query("query") String query, @Query("songCount") int songCount, @Query("albumCount") int albumCount, @Query("artistCount") int artistCount); Call<ApiResponse> search2(@QueryMap Map<String, String> params, @Query("query") String query, @Query("songCount") int songCount, @Query("albumCount") int albumCount, @Query("artistCount") int artistCount);
@GET("search3") @GET("search3")
Call<SubsonicResponse> search3(@QueryMap Map<String, String> params, @Query("query") String query, @Query("songCount") int songCount, @Query("albumCount") int albumCount, @Query("artistCount") int artistCount); Call<ApiResponse> search3(@QueryMap Map<String, String> params, @Query("query") String query, @Query("songCount") int songCount, @Query("albumCount") int albumCount, @Query("artistCount") int artistCount);
} }

View file

@ -4,9 +4,10 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import com.cappielloantonio.play.subsonic.Subsonic; import com.cappielloantonio.play.subsonic.Subsonic;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import com.cappielloantonio.play.subsonic.utils.CacheUtil; import com.cappielloantonio.play.subsonic.utils.CacheUtil;
import com.tickaroo.tikxml.retrofit.TikXmlConverterFactory; import com.google.gson.GsonBuilder;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -15,6 +16,7 @@ import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class SystemClient { public class SystemClient {
private static final String TAG = "SystemClient"; private static final String TAG = "SystemClient";
@ -29,19 +31,19 @@ public class SystemClient {
Retrofit retrofit = new Retrofit.Builder() Retrofit retrofit = new Retrofit.Builder()
.baseUrl(subsonic.getUrl()) .baseUrl(subsonic.getUrl())
.addConverterFactory(TikXmlConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().create()))
.client(getOkHttpClient()) .client(getOkHttpClient())
.build(); .build();
this.systemService = retrofit.create(SystemService.class); this.systemService = retrofit.create(SystemService.class);
} }
public Call<SubsonicResponse> ping() { public Call<ApiResponse> ping() {
Log.d(TAG, "ping()"); Log.d(TAG, "ping()");
return systemService.ping(subsonic.getParams()); return systemService.ping(subsonic.getParams());
} }
public Call<SubsonicResponse> getLicense() { public Call<ApiResponse> getLicense() {
Log.d(TAG, "getLicense()"); Log.d(TAG, "getLicense()");
return systemService.getLicense(subsonic.getParams()); return systemService.getLicense(subsonic.getParams());
} }

View file

@ -1,6 +1,6 @@
package com.cappielloantonio.play.subsonic.api.system; package com.cappielloantonio.play.subsonic.api.system;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.base.ApiResponse;
import java.util.Map; import java.util.Map;
@ -10,8 +10,8 @@ import retrofit2.http.QueryMap;
public interface SystemService { public interface SystemService {
@GET("ping") @GET("ping")
Call<SubsonicResponse> ping(@QueryMap Map<String, String> params); Call<ApiResponse> ping(@QueryMap Map<String, String> params);
@GET("getLicense") @GET("getLicense")
Call<SubsonicResponse> getLicense(@QueryMap Map<String, String> params); Call<ApiResponse> getLicense(@QueryMap Map<String, String> params);
} }

View file

@ -0,0 +1,9 @@
package com.cappielloantonio.play.subsonic.base
import com.cappielloantonio.play.subsonic.models.SubsonicResponse
import com.google.gson.annotations.SerializedName
class ApiResponse {
@SerializedName("subsonic-response")
var subsonicResponse: SubsonicResponse? = null
}

View file

@ -1,48 +1,25 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import android.os.Parcelable import android.os.Parcelable
import com.tickaroo.tikxml.annotation.Attribute import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
import com.tickaroo.tikxml.converters.date.rfc3339.DateRfc3339TypeConverter
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
import java.util.* import java.util.*
@Parcelize @Parcelize
@Xml(name = "album")
open class AlbumID3 : Parcelable { open class AlbumID3 : Parcelable {
@Attribute
var id: String? = null var id: String? = null
@Attribute
var name: String? = null var name: String? = null
@Attribute
var artist: String? = null var artist: String? = null
@Attribute
var artistId: String? = null var artistId: String? = null
@Attribute(name = "coverArt") @SerializedName("coverArt")
var coverArtId: String? = null var coverArtId: String? = null
@Attribute
var songCount = 0 var songCount = 0
@Attribute
var duration = 0 var duration = 0
@Attribute
var playCount: Long? = null var playCount: Long? = null
@Attribute(converter = DateRfc3339TypeConverter::class)
var created: Date? = null var created: Date? = null
@Attribute(converter = DateRfc3339TypeConverter::class)
var starred: Date? = null var starred: Date? = null
@Attribute
var year: Int? = null var year: Int? = null
@Attribute
var genre: String? = null var genre: String? = null
} }

View file

@ -1,25 +1,11 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Attribute
import com.tickaroo.tikxml.annotation.Xml
@Xml
class AlbumInfo { class AlbumInfo {
@Attribute
var notes: String? = null var notes: String? = null
@Attribute
var musicBrainzId: String? = null var musicBrainzId: String? = null
@Attribute
var lastFmUrl: String? = null var lastFmUrl: String? = null
@Attribute
var smallImageUrl: String? = null var smallImageUrl: String? = null
@Attribute
var mediumImageUrl: String? = null var mediumImageUrl: String? = null
@Attribute
var largeImageUrl: String? = null var largeImageUrl: String? = null
} }

View file

@ -1,10 +1,8 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class AlbumList2 { class AlbumList2 {
@Element @SerializedName("album")
var albums: List<AlbumID3>? = null var albums: List<AlbumID3>? = null
} }

View file

@ -1,13 +1,11 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import android.os.Parcelable import android.os.Parcelable
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@Parcelize @Parcelize
@Xml
class AlbumWithSongsID3 : AlbumID3(), Parcelable { class AlbumWithSongsID3 : AlbumID3(), Parcelable {
@Element(name = "song") @SerializedName("song")
var songs: List<Child>? = null var songs: List<Child>? = null
} }

View file

@ -1,27 +1,17 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import android.os.Parcelable import android.os.Parcelable
import com.tickaroo.tikxml.annotation.Attribute import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
import com.tickaroo.tikxml.converters.date.rfc3339.DateRfc3339TypeConverter
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
import java.util.* import java.util.*
@Parcelize @Parcelize
@Xml(name = "artist")
open class ArtistID3 : Parcelable { open class ArtistID3 : Parcelable {
@Attribute
var id: String? = null var id: String? = null
@Attribute
var name: String? = null var name: String? = null
@Attribute(name = "coverArt") @SerializedName("coverArt")
var coverArtId: String? = null var coverArtId: String? = null
@Attribute
var albumCount = 0 var albumCount = 0
@Attribute(converter = DateRfc3339TypeConverter::class)
var starred: Date? = null var starred: Date? = null
} }

View file

@ -1,10 +1,9 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml import java.util.*
@Xml
class ArtistInfo2 : ArtistInfoBase() { class ArtistInfo2 : ArtistInfoBase() {
@Element(name = "similarArtist") @SerializedName("similarArtist")
var similarArtists: List<SimilarArtistID3>? = null var similarArtists: List<SimilarArtistID3>? = emptyList()
} }

View file

@ -1,25 +1,10 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.PropertyElement
import com.tickaroo.tikxml.annotation.Xml
@Xml
open class ArtistInfoBase { open class ArtistInfoBase {
@PropertyElement
var biography: String? = null var biography: String? = null
@PropertyElement
var musicBrainzId: String? = null var musicBrainzId: String? = null
@PropertyElement
var lastFmUrl: String? = null var lastFmUrl: String? = null
@PropertyElement
var smallImageUrl: String? = null var smallImageUrl: String? = null
@PropertyElement
var mediumImageUrl: String? = null var mediumImageUrl: String? = null
@PropertyElement
var largeImageUrl: String? = null var largeImageUrl: String? = null
} }

View file

@ -1,13 +1,11 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import android.os.Parcelable import android.os.Parcelable
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@Parcelize @Parcelize
@Xml
class ArtistWithAlbumsID3 : ArtistID3(), Parcelable { class ArtistWithAlbumsID3 : ArtistID3(), Parcelable {
@Element(name = "album") @SerializedName("album")
var albums: List<AlbumID3>? = null var albums: List<AlbumID3>? = null
} }

View file

@ -1,11 +1,9 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class ArtistsID3 { class ArtistsID3 {
@Element(name = "index") @SerializedName("index")
var indices: List<IndexID3>? = null var indices: List<IndexID3>? = null
var ignoredArticles: String? = null var ignoredArticles: String? = null
} }

View file

@ -3,137 +3,108 @@ package com.cappielloantonio.play.subsonic.models
import android.os.Parcelable import android.os.Parcelable
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.tickaroo.tikxml.annotation.Attribute import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
import com.tickaroo.tikxml.converters.date.rfc3339.DateRfc3339TypeConverter
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
import java.util.* import java.util.*
@Parcelize @Parcelize
@Xml
open class Child( open class Child(
@PrimaryKey @PrimaryKey
@ColumnInfo(name = "id") @ColumnInfo(name = "id")
@Attribute
open val id: String, open val id: String,
@ColumnInfo(name = "parent_id") @ColumnInfo(name = "parent_id")
@Attribute(name = "parent") @SerializedName("parent")
var parentId: String? = null, var parentId: String? = null,
@ColumnInfo(name = "is_dir") @ColumnInfo(name = "is_dir")
@Attribute
var isDir: Boolean = false, var isDir: Boolean = false,
@ColumnInfo @ColumnInfo
@Attribute
var title: String? = null, var title: String? = null,
@ColumnInfo @ColumnInfo
@Attribute
var album: String? = null, var album: String? = null,
@ColumnInfo @ColumnInfo
@Attribute
var artist: String? = null, var artist: String? = null,
@ColumnInfo @ColumnInfo
@Attribute
var track: Int? = null, var track: Int? = null,
@ColumnInfo @ColumnInfo
@Attribute
var year: Int? = null, var year: Int? = null,
@ColumnInfo @ColumnInfo
@Attribute(name = "genre") @SerializedName("genre")
var genre: String? = null, var genre: String? = null,
@ColumnInfo(name = "cover_art_id") @ColumnInfo(name = "cover_art_id")
@Attribute(name = "coverArt") @SerializedName("coverArt")
var coverArtId: String? = null, var coverArtId: String? = null,
@ColumnInfo @ColumnInfo
@Attribute
var size: Long? = null, var size: Long? = null,
@ColumnInfo(name = "content_type") @ColumnInfo(name = "content_type")
@Attribute
var contentType: String? = null, var contentType: String? = null,
@ColumnInfo @ColumnInfo
@Attribute
var suffix: String? = null, var suffix: String? = null,
@ColumnInfo("transcoding_content_type") @ColumnInfo("transcoding_content_type")
@Attribute
var transcodedContentType: String? = null, var transcodedContentType: String? = null,
@ColumnInfo(name = "transcoded_suffix") @ColumnInfo(name = "transcoded_suffix")
@Attribute
var transcodedSuffix: String? = null, var transcodedSuffix: String? = null,
@ColumnInfo @ColumnInfo
@Attribute
var duration: Int? = null, var duration: Int? = null,
@ColumnInfo("bitrate") @ColumnInfo("bitrate")
@Attribute(name = "bitRate") @SerializedName("bitRate")
var bitrate: Int? = null, var bitrate: Int? = null,
@ColumnInfo @ColumnInfo
@Attribute
var path: String? = null, var path: String? = null,
@ColumnInfo(name = "is_video") @ColumnInfo(name = "is_video")
@Attribute(name = "isVideo") @SerializedName("isVideo")
var isVideo: Boolean = false, var isVideo: Boolean = false,
@ColumnInfo(name = "user_rating") @ColumnInfo(name = "user_rating")
@Attribute
var userRating: Int? = null, var userRating: Int? = null,
@ColumnInfo(name = "average_rating") @ColumnInfo(name = "average_rating")
@Attribute
var averageRating: Double? = null, var averageRating: Double? = null,
@ColumnInfo(name = "play_count") @ColumnInfo(name = "play_count")
@Attribute
var playCount: Long? = null, var playCount: Long? = null,
@ColumnInfo(name = "disc_number") @ColumnInfo(name = "disc_number")
@Attribute
var discNumber: Int? = null, var discNumber: Int? = null,
@ColumnInfo @ColumnInfo
@Attribute(converter = DateRfc3339TypeConverter::class)
var created: Date? = null, var created: Date? = null,
@ColumnInfo @ColumnInfo
@Attribute(converter = DateRfc3339TypeConverter::class)
var starred: Date? = null, var starred: Date? = null,
@ColumnInfo(name = "album_id") @ColumnInfo(name = "album_id")
@Attribute
var albumId: String? = null, var albumId: String? = null,
@ColumnInfo(name = "artist_id") @ColumnInfo(name = "artist_id")
@Attribute
var artistId: String? = null, var artistId: String? = null,
@ColumnInfo @ColumnInfo
@Attribute
var type: String? = null, var type: String? = null,
@ColumnInfo(name = "bookmark_position") @ColumnInfo(name = "bookmark_position")
@Attribute
var bookmarkPosition: Long? = null, var bookmarkPosition: Long? = null,
@ColumnInfo(name = "original_width") @ColumnInfo(name = "original_width")
@Attribute
var originalWidth: Int? = null, var originalWidth: Int? = null,
@ColumnInfo(name = "original_height") @ColumnInfo(name = "original_height")
@Attribute
var originalHeight: Int? = null var originalHeight: Int? = null
) : Parcelable ) : Parcelable

View file

@ -1,14 +1,7 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.cappielloantonio.play.subsonic.utils.converter.ErrorCodeConverter
import com.tickaroo.tikxml.annotation.Attribute
import com.tickaroo.tikxml.annotation.Xml
@Xml
class Error { class Error {
@Attribute(converter = ErrorCodeConverter::class)
var code: ErrorCode? = null var code: ErrorCode? = null
@Attribute
var message: String? = null var message: String? = null
} }

View file

@ -1,20 +1,13 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import android.os.Parcelable import android.os.Parcelable
import com.tickaroo.tikxml.annotation.Attribute import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.TextContent
import com.tickaroo.tikxml.annotation.Xml
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@Parcelize @Parcelize
@Xml
class Genre : Parcelable { class Genre : Parcelable {
@TextContent @SerializedName("value")
var genre: String? = null var genre: String? = null
@Attribute
var songCount = 0 var songCount = 0
@Attribute
var albumCount = 0 var albumCount = 0
} }

View file

@ -1,10 +1,8 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class Genres { class Genres {
@Element @SerializedName("genre")
var genres: List<Genre>? = null var genres: List<Genre>? = null
} }

View file

@ -1,11 +1,9 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class IndexID3 { class IndexID3 {
@Element(name = "artist") @SerializedName("artist")
var artists: List<ArtistID3>? = null var artists: List<ArtistID3>? = null
var name: String? = null var name: String? = null
} }

View file

@ -1,17 +1,7 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Attribute
import com.tickaroo.tikxml.annotation.TextContent
import com.tickaroo.tikxml.annotation.Xml
@Xml(name = "lyrics")
class Lyrics { class Lyrics {
@TextContent
var content: String? = null var content: String? = null
@Attribute
var artist: String? = null var artist: String? = null
@Attribute
var title: String? = null var title: String? = null
} }

View file

@ -1,11 +1,6 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Attribute
import com.tickaroo.tikxml.annotation.Xml
@Xml
class MediaType { class MediaType {
@Attribute
var value: String? = null var value: String? = null
companion object { companion object {

View file

@ -1,13 +1,6 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Attribute
import com.tickaroo.tikxml.annotation.Xml
@Xml
class MusicFolder { class MusicFolder {
@Attribute
var id = 0 var id = 0
@Attribute
var name: String? = null var name: String? = null
} }

View file

@ -1,10 +1,5 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element
import com.tickaroo.tikxml.annotation.Xml
@Xml
class MusicFolders { class MusicFolders {
@Element
var musicFolders: List<MusicFolder>? = null var musicFolders: List<MusicFolder>? = null
} }

View file

@ -1,10 +1,8 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class NewestPodcasts { class NewestPodcasts {
@Element(name = "episode") @SerializedName("episode")
var episodes: List<PodcastEpisode>? = null var episodes: List<PodcastEpisode>? = null
} }

View file

@ -1,9 +1,14 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.google.gson.annotations.SerializedName
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@Parcelize @Parcelize
class NowPlayingEntry(override val id: String) : Child(id) { class NowPlayingEntry(
// TODO
@SerializedName("_id")
override val id: String
) : Child(id) {
var username: String? = null var username: String? = null
var minutesAgo = 0 var minutesAgo = 0
var playerId = 0 var playerId = 0

View file

@ -5,60 +5,45 @@ import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.Ignore import androidx.room.Ignore
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.tickaroo.tikxml.annotation.Attribute import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
import com.tickaroo.tikxml.converters.date.rfc3339.DateRfc3339TypeConverter
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
import java.util.* import java.util.*
@Parcelize @Parcelize
@Entity(tableName = "playlist") @Entity(tableName = "playlist")
@Xml open class Playlist(
open class Playlist : Parcelable {
@PrimaryKey @PrimaryKey
@ColumnInfo(name = "id") @ColumnInfo(name = "id")
@Attribute open var id: String
lateinit var id: String ) : Parcelable {
@ColumnInfo(name = "name") @ColumnInfo(name = "name")
@Attribute
var name: String? = null var name: String? = null
@Ignore @Ignore
@Attribute
var comment: String? = null var comment: String? = null
@Ignore @Ignore
@Attribute
var owner: String? = null var owner: String? = null
@Ignore @Ignore
@Attribute(name = "public") @SerializedName("public")
var isUniversal: Boolean? = null var isUniversal: Boolean? = null
@Ignore @Ignore
@Attribute
var songCount: Int = 0 var songCount: Int = 0
@Ignore
@ColumnInfo(name = "duration") @ColumnInfo(name = "duration")
@Attribute
var duration: Long = 0 var duration: Long = 0
@Ignore @Ignore
@Attribute(converter = DateRfc3339TypeConverter::class)
var created: Date? = null var created: Date? = null
@Ignore @Ignore
@Attribute(converter = DateRfc3339TypeConverter::class)
var changed: Date? = null var changed: Date? = null
@Ignore
@ColumnInfo(name = "coverArt") @ColumnInfo(name = "coverArt")
@Attribute
var coverArtId: String? = null var coverArtId: String? = null
@Ignore @Ignore
@Attribute
var allowedUsers: List<String>? = null var allowedUsers: List<String>? = null
} }

View file

@ -1,13 +1,14 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import android.os.Parcelable import android.os.Parcelable
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@Parcelize @Parcelize
@Xml class PlaylistWithSongs(
class PlaylistWithSongs : Playlist(), Parcelable { @SerializedName("_id")
@Element(name = "entry") override var id: String
) : Playlist(id), Parcelable {
@SerializedName("entry")
var entries: List<Child>? = null var entries: List<Child>? = null
} }

View file

@ -1,10 +1,8 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml class Playlists(
class Playlists { @SerializedName("playlist")
@Element(name = "playlist")
var playlists: List<Playlist>? = null var playlists: List<Playlist>? = null
} )

View file

@ -1,38 +1,19 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import android.os.Parcelable import android.os.Parcelable
import com.tickaroo.tikxml.annotation.Attribute import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Element
import com.tickaroo.tikxml.annotation.Xml
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@Parcelize @Parcelize
@Xml
class PodcastChannel : Parcelable { class PodcastChannel : Parcelable {
@Element(name = "episode") @SerializedName("episode")
var episodes: List<PodcastEpisode>? = null var episodes: List<PodcastEpisode>? = null
@Attribute
var id: String? = null var id: String? = null
@Attribute
var url: String? = null var url: String? = null
@Attribute
var title: String? = null var title: String? = null
@Attribute
var description: String? = null var description: String? = null
@Attribute
var coverArtId: String? = null var coverArtId: String? = null
@Attribute
var originalImageUrl: String? = null var originalImageUrl: String? = null
@Attribute
var status: String? = null var status: String? = null
@Attribute
var errorMessage: String? = null var errorMessage: String? = null
} }

View file

@ -1,120 +1,54 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import android.os.Parcelable import android.os.Parcelable
import com.tickaroo.tikxml.annotation.Attribute import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
import com.tickaroo.tikxml.converters.date.rfc3339.DateRfc3339TypeConverter
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
import java.util.* import java.util.*
@Parcelize @Parcelize
@Xml
class PodcastEpisode : Parcelable { class PodcastEpisode : Parcelable {
@Attribute
var id: String? = null var id: String? = null
@Attribute(name = "parent") @SerializedName("parent")
var parentId: String? = null var parentId: String? = null
@Attribute(name = "isDir") @SerializedName("isDir")
var isDir = false var isDir = false
@Attribute
var title: String? = null var title: String? = null
@Attribute
var album: String? = null var album: String? = null
@Attribute
var artist: String? = null var artist: String? = null
@Attribute
var track: Int? = null var track: Int? = null
@Attribute
var year: Int? = null var year: Int? = null
@Attribute(name = "genre")
var genre: String? = null var genre: String? = null
@Attribute(name = "coverArt") @SerializedName("coverArt")
var coverArtId: String? = null var coverArtId: String? = null
@Attribute
var size: Long? = null var size: Long? = null
@Attribute
var contentType: String? = null var contentType: String? = null
@Attribute
var suffix: String? = null var suffix: String? = null
@Attribute
var transcodedContentType: String? = null var transcodedContentType: String? = null
@Attribute
var transcodedSuffix: String? = null var transcodedSuffix: String? = null
@Attribute
var duration: Int? = null var duration: Int? = null
@Attribute
var bitRate: Int? = null var bitRate: Int? = null
@Attribute
var path: String? = null var path: String? = null
@Attribute(name = "isVideo") @SerializedName("isVideo")
var video: Boolean? = null var video: Boolean? = null
@Attribute
var userRating: Int? = null var userRating: Int? = null
@Attribute
var averageRating: Double? = null var averageRating: Double? = null
@Attribute
var playCount: Long? = null var playCount: Long? = null
@Attribute
var discNumber: Int? = null var discNumber: Int? = null
@Attribute(converter = DateRfc3339TypeConverter::class)
var created: Date? = null var created: Date? = null
@Attribute(converter = DateRfc3339TypeConverter::class)
var starred: Date? = null var starred: Date? = null
@Attribute
var albumId: String? = null var albumId: String? = null
@Attribute
var artistId: String? = null var artistId: String? = null
@Attribute
var type: String? = null var type: String? = null
@Attribute
var bookmarkPosition: Long? = null var bookmarkPosition: Long? = null
@Attribute
var originalWidth: Int? = null var originalWidth: Int? = null
@Attribute
var originalHeight: Int? = null var originalHeight: Int? = null
@Attribute
var streamId: String? = null var streamId: String? = null
@Attribute
var channelId: String? = null var channelId: String? = null
@Attribute
var description: String? = null var description: String? = null
@Attribute
var status: String? = null var status: String? = null
@Attribute(converter = DateRfc3339TypeConverter::class)
var publishDate: Date? = null var publishDate: Date? = null
} }

View file

@ -1,11 +1,6 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Attribute
import com.tickaroo.tikxml.annotation.Xml
@Xml
class PodcastStatus { class PodcastStatus {
@Attribute
var value: String? = null var value: String? = null
companion object { companion object {

View file

@ -1,10 +1,8 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class Podcasts { class Podcasts {
@Element(name = "channel") @SerializedName("channel")
var channels: List<PodcastChannel>? = null var channels: List<PodcastChannel>? = null
} }

View file

@ -1,10 +1,6 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Attribute class ResponseStatus(val value: String) {
import com.tickaroo.tikxml.annotation.Xml
@Xml
class ResponseStatus(@param:Attribute val value: String) {
companion object { companion object {
@JvmField @JvmField

View file

@ -1,13 +1,6 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Attribute
import com.tickaroo.tikxml.annotation.Xml
@Xml
class ScanStatus { class ScanStatus {
@Attribute
var isScanning = false var isScanning = false
@Attribute
var count: Long? = null var count: Long? = null
} }

View file

@ -1,16 +1,14 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class SearchResult2 { class SearchResult2 {
@Element(name = "artist") @SerializedName("artist")
var artists: List<Artist>? = null var artists: List<Artist>? = null
@Element(name = "album") @SerializedName("album")
var albums: List<Child>? = null var albums: List<Child>? = null
@Element(name = "song") @SerializedName("song")
var songs: List<Child>? = null var songs: List<Child>? = null
} }

View file

@ -1,16 +1,14 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class SearchResult3 { class SearchResult3 {
@Element(name = "artist") @SerializedName("artist")
var artists: List<ArtistID3>? = null var artists: List<ArtistID3>? = null
@Element(name = "album") @SerializedName("album")
var albums: List<AlbumID3>? = null var albums: List<AlbumID3>? = null
@Element(name = "song") @SerializedName("song")
var songs: List<Child>? = null var songs: List<Child>? = null
} }

View file

@ -1,22 +1,7 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import android.os.Parcelable import android.os.Parcelable
import com.tickaroo.tikxml.annotation.Attribute
import com.tickaroo.tikxml.annotation.Xml
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@Parcelize @Parcelize
@Xml(name = "similarArtist") class SimilarArtistID3 : ArtistID3(), Parcelable
class SimilarArtistID3 : Parcelable {
@Attribute
var id: String? = null
@Attribute
var name: String? = null
@Attribute(name = "coverArt")
var coverArtId: String? = null
@Attribute
var albumCount = 0
}

View file

@ -1,10 +1,8 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class SimilarSongs2 { class SimilarSongs2 {
@Element(name = "song") @SerializedName("song")
var songs: List<Child>? = null var songs: List<Child>? = null
} }

View file

@ -1,10 +1,8 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class Songs { class Songs {
@Element(name = "song") @SerializedName("song")
var songs: List<Child>? = null var songs: List<Child>? = null
} }

View file

@ -1,16 +1,14 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class Starred2 { class Starred2 {
@Element(name = "artist") @SerializedName("artist")
var artists: List<ArtistID3>? = null var artists: List<ArtistID3>? = null
@Element(name = "album") @SerializedName("album")
var albums: List<AlbumID3>? = null var albums: List<AlbumID3>? = null
@Element(name = "song") @SerializedName("song")
var songs: List<Child>? = null var songs: List<Child>? = null
} }

View file

@ -1,54 +1,25 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.cappielloantonio.play.subsonic.utils.converter.ResponseStatusConverter
import com.tickaroo.tikxml.annotation.Attribute
import com.tickaroo.tikxml.annotation.Element
import com.tickaroo.tikxml.annotation.Xml
@Xml(name = "subsonic-response")
class SubsonicResponse { class SubsonicResponse {
@Element
var error: Error? = null var error: Error? = null
@Element(name = "scanStatus")
var scanStatus: ScanStatus? = null var scanStatus: ScanStatus? = null
@Element(name = "topSongs")
var topSongs: TopSongs? = null var topSongs: TopSongs? = null
@Element(name = "similarSongs2")
var similarSongs2: SimilarSongs2? = null var similarSongs2: SimilarSongs2? = null
var similarSongs: SimilarSongs? = null var similarSongs: SimilarSongs? = null
@Element(name = "artistInfo2")
var artistInfo2: ArtistInfo2? = null var artistInfo2: ArtistInfo2? = null
var artistInfo: ArtistInfo? = null var artistInfo: ArtistInfo? = null
@Element(name = "albumInfo")
var albumInfo: AlbumInfo? = null var albumInfo: AlbumInfo? = null
@Element(name = "starred2")
var starred2: Starred2? = null var starred2: Starred2? = null
var starred: Starred? = null var starred: Starred? = null
var shares: Shares? = null var shares: Shares? = null
var playQueue: PlayQueue? = null var playQueue: PlayQueue? = null
var bookmarks: Bookmarks? = null var bookmarks: Bookmarks? = null
var internetRadioStations: InternetRadioStations? = null var internetRadioStations: InternetRadioStations? = null
@Element(name = "newestPodcasts")
var newestPodcasts: NewestPodcasts? = null var newestPodcasts: NewestPodcasts? = null
var podcasts: Podcasts? = null var podcasts: Podcasts? = null
@Element(name = "lyrics")
var lyrics: Lyrics? = null var lyrics: Lyrics? = null
@Element(name = "songsByGenre")
var songsByGenre: Songs? = null var songsByGenre: Songs? = null
@Element(name = "randomSongs")
var randomSongs: Songs? = null var randomSongs: Songs? = null
@Element
var albumList2: AlbumList2? = null var albumList2: AlbumList2? = null
var albumList: AlbumList? = null var albumList: AlbumList? = null
var chatMessages: ChatMessages? = null var chatMessages: ChatMessages? = null
@ -57,52 +28,24 @@ class SubsonicResponse {
var license: License? = null var license: License? = null
var jukeboxPlaylist: JukeboxPlaylist? = null var jukeboxPlaylist: JukeboxPlaylist? = null
var jukeboxStatus: JukeboxStatus? = null var jukeboxStatus: JukeboxStatus? = null
@Element(name = "playlist")
var playlist: PlaylistWithSongs? = null var playlist: PlaylistWithSongs? = null
@Element
var playlists: Playlists? = null var playlists: Playlists? = null
@Element
var searchResult3: SearchResult3? = null var searchResult3: SearchResult3? = null
@Element
var searchResult2: SearchResult2? = null var searchResult2: SearchResult2? = null
var searchResult: SearchResult? = null var searchResult: SearchResult? = null
var nowPlaying: NowPlaying? = null var nowPlaying: NowPlaying? = null
var videoInfo: VideoInfo? = null var videoInfo: VideoInfo? = null
var videos: Videos? = null var videos: Videos? = null
@Element(name = "song")
var song: Child? = null var song: Child? = null
@Element(name = "album")
var album: AlbumWithSongsID3? = null var album: AlbumWithSongsID3? = null
@Element(name = "artist")
var artist: ArtistWithAlbumsID3? = null var artist: ArtistWithAlbumsID3? = null
@Element(name = "artists")
var artists: ArtistsID3? = null var artists: ArtistsID3? = null
@Element
var genres: Genres? = null var genres: Genres? = null
var directory: Directory? = null var directory: Directory? = null
var indexes: Indexes? = null var indexes: Indexes? = null
@Element
var musicFolders: MusicFolders? = null var musicFolders: MusicFolders? = null
var status: String? = null
@Attribute(converter = ResponseStatusConverter::class)
var status: ResponseStatus? = null
@Attribute
var version: String? = null var version: String? = null
@Attribute
var type: String? = null var type: String? = null
@Attribute
var serverVersion: String? = null var serverVersion: String? = null
} }

View file

@ -1,10 +1,8 @@
package com.cappielloantonio.play.subsonic.models package com.cappielloantonio.play.subsonic.models
import com.tickaroo.tikxml.annotation.Element import com.google.gson.annotations.SerializedName
import com.tickaroo.tikxml.annotation.Xml
@Xml
class TopSongs { class TopSongs {
@Element(name = "song") @SerializedName("song")
var songs: List<Child>? = null var songs: List<Child>? = null
} }

View file

@ -1,16 +0,0 @@
package com.cappielloantonio.play.subsonic.utils.converter;
import com.cappielloantonio.play.subsonic.models.ErrorCode;
import com.tickaroo.tikxml.TypeConverter;
public class ErrorCodeConverter implements TypeConverter<ErrorCode> {
@Override
public ErrorCode read(String value) throws Exception {
return new ErrorCode(Integer.parseInt(value));
}
@Override
public String write(ErrorCode value) throws Exception {
return String.valueOf(value.getValue());
}
}

View file

@ -1,16 +0,0 @@
package com.cappielloantonio.play.subsonic.utils.converter;
import com.cappielloantonio.play.subsonic.models.ResponseStatus;
import com.tickaroo.tikxml.TypeConverter;
public class ResponseStatusConverter implements TypeConverter<ResponseStatus> {
@Override
public ResponseStatus read(String value) throws Exception {
return new ResponseStatus(value);
}
@Override
public String write(ResponseStatus value) throws Exception {
return value.getValue();
}
}

View file

@ -98,7 +98,7 @@ public class PlaylistChooserDialog extends DialogFragment implements ClickCallba
@Override @Override
public void onPlaylistClick(Bundle bundle) { public void onPlaylistClick(Bundle bundle) {
Playlist playlist = requireArguments().getParcelable("playlist_object"); Playlist playlist = bundle.getParcelable("playlist_object");
playlistChooserViewModel.addSongToPlaylist(playlist.getId()); playlistChooserViewModel.addSongToPlaylist(playlist.getId());
dismiss(); dismiss();
} }

View file

@ -541,7 +541,7 @@ public class HomeFragment extends Fragment implements ClickCallback {
bind.homeMostPlayedAlbumsPlaceholder.placeholder.setVisibility(View.GONE); bind.homeMostPlayedAlbumsPlaceholder.placeholder.setVisibility(View.GONE);
if (bind != null) if (bind != null)
bind.homeMostPlayedAlbumsSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE); bind.homeMostPlayedAlbumsSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
if (albums.size() < 5) reorder(); // if (albums.size() < 5) reorder();
mostPlayedAlbumAdapter.setItems(albums); mostPlayedAlbumAdapter.setItems(albums);
} }
@ -714,19 +714,21 @@ public class HomeFragment extends Fragment implements ClickCallback {
public void reorder() { public void reorder() {
if (bind != null) { if (bind != null) {
bind.homeLinearLayoutContainer.removeAllViews(); // bind.homeLinearLayoutContainer.removeAllViews();
bind.homeLinearLayoutContainer.addView(bind.homeDiscoverSector); // bind.homeLinearLayoutContainer.addView(bind.homeDiscoverSector);
// bind.homeLinearLayoutContainer.addView(bind.homeSimilarTracksSector); // bind.homeLinearLayoutContainer.addView(bind.homeSimilarTracksSector);
// bind.homeLinearLayoutContainer.addView(bind.homeRadioArtistSector); // bind.homeLinearLayoutContainer.addView(bind.homeRadioArtistSector);
// bind.homeLinearLayoutContainer.addView(bind.homeGridTracksSector); // bind.homeLinearLayoutContainer.addView(bind.homeGridTracksSector);
// bind.homeLinearLayoutContainer.addView(bind.starredTracksSector); // bind.homeLinearLayoutContainer.addView(bind.starredTracksSector);
// bind.homeLinearLayoutContainer.addView(bind.starredAlbumsSector); // bind.homeLinearLayoutContainer.addView(bind.starredAlbumsSector);
// bind.homeLinearLayoutContainer.addView(bind.starredArtistsSector); // bind.homeLinearLayoutContainer.addView(bind.starredArtistsSector);
bind.homeLinearLayoutContainer.addView(bind.homeRecentlyAddedAlbumsSector);
bind.homeLinearLayoutContainer.addView(bind.homeFlashbackSector); // bind.homeLinearLayoutContainer.addView(bind.homeRecentlyAddedAlbumsSector);
bind.homeLinearLayoutContainer.addView(bind.homeMostPlayedAlbumsSector); // bind.homeLinearLayoutContainer.addView(bind.homeFlashbackSector);
bind.homeLinearLayoutContainer.addView(bind.homeRecentlyPlayedAlbumsSector); // bind.homeLinearLayoutContainer.addView(bind.homeMostPlayedAlbumsSector);
bind.homeLinearLayoutContainer.addView(bind.homeNewestPodcastsSector); // bind.homeLinearLayoutContainer.addView(bind.homeRecentlyPlayedAlbumsSector);
// bind.homeLinearLayoutContainer.addView(bind.homeNewestPodcastsSector);
} }
} }

View file

@ -3,17 +3,18 @@ package com.cappielloantonio.play.ui.fragment;
import android.content.ComponentName; import android.content.ComponentName;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.media3.common.MediaMetadata; import androidx.media3.common.MediaMetadata;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.session.MediaBrowser; import androidx.media3.session.MediaBrowser;
import androidx.media3.session.MediaController; import androidx.media3.session.MediaController;
import androidx.media3.session.SessionToken; import androidx.media3.session.SessionToken;
@ -33,9 +34,8 @@ import com.google.android.material.elevation.SurfaceColors;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
@OptIn(markerClass = UnstableApi.class)
public class PlayerBottomSheetFragment extends Fragment { public class PlayerBottomSheetFragment extends Fragment {
private static final String TAG = "PlayerBottomSheetFragment";
private FragmentPlayerBottomSheetBinding bind; private FragmentPlayerBottomSheetBinding bind;
private PlayerBottomSheetViewModel playerBottomSheetViewModel; private PlayerBottomSheetViewModel playerBottomSheetViewModel;
@ -142,24 +142,24 @@ public class PlayerBottomSheetFragment extends Fragment {
} }
private void setMetadata(MediaMetadata mediaMetadata) { private void setMetadata(MediaMetadata mediaMetadata) {
if (mediaMetadata.extras != null) if (mediaMetadata.extras != null) {
playerBottomSheetViewModel.setLiveMedia(getViewLifecycleOwner(), mediaMetadata.extras.getString("mediaType"), mediaMetadata.extras.getString("id")); playerBottomSheetViewModel.setLiveMedia(getViewLifecycleOwner(), mediaMetadata.extras.getString("type"), mediaMetadata.extras.getString("id"));
if (mediaMetadata.extras != null) playerBottomSheetViewModel.setLiveArtist(getViewLifecycleOwner(), mediaMetadata.extras.getString("type"), mediaMetadata.extras.getString("artistId"));
playerBottomSheetViewModel.setLiveArtist(getViewLifecycleOwner(), mediaMetadata.extras.getString("mediaType"), mediaMetadata.extras.getString("artistId"));
bind.playerHeaderLayout.playerHeaderMediaTitleLabel.setText(MusicUtil.getReadableString(String.valueOf(mediaMetadata.title))); bind.playerHeaderLayout.playerHeaderMediaTitleLabel.setText(MusicUtil.getReadableString(mediaMetadata.extras.getString("title")));
bind.playerHeaderLayout.playerHeaderMediaArtistLabel.setText(MusicUtil.getReadableString(String.valueOf(mediaMetadata.artist))); bind.playerHeaderLayout.playerHeaderMediaArtistLabel.setText(MusicUtil.getReadableString(mediaMetadata.extras.getString("artist")));
if (mediaMetadata.extras != null) CustomGlideRequest.Builder CustomGlideRequest.Builder
.from(requireContext(), mediaMetadata.extras.getString("coverArtId"), CustomGlideRequest.SONG_PIC, null) .from(requireContext(), mediaMetadata.extras.getString("coverArtId"), CustomGlideRequest.SONG_PIC, null)
.build() .build()
.transform(new CenterCrop(), new RoundedCorners(CustomGlideRequest.CORNER_RADIUS)) .transform(new CenterCrop(), new RoundedCorners(CustomGlideRequest.CORNER_RADIUS))
.into(bind.playerHeaderLayout.playerHeaderMediaCoverImage); .into(bind.playerHeaderLayout.playerHeaderMediaCoverImage);
}
} }
private void setMediaControllerUI(MediaBrowser mediaBrowser) { private void setMediaControllerUI(MediaBrowser mediaBrowser) {
if (mediaBrowser.getMediaMetadata().extras != null) { if (mediaBrowser.getMediaMetadata().extras != null) {
switch (mediaBrowser.getMediaMetadata().extras.getString("mediaType", Media.MEDIA_TYPE_MUSIC)) { switch (mediaBrowser.getMediaMetadata().extras.getString("type", Media.MEDIA_TYPE_MUSIC)) {
case Media.MEDIA_TYPE_PODCAST: case Media.MEDIA_TYPE_PODCAST:
bind.playerHeaderLayout.playerHeaderFastForwardMediaButton.setVisibility(View.VISIBLE); bind.playerHeaderLayout.playerHeaderFastForwardMediaButton.setVisibility(View.VISIBLE);
bind.playerHeaderLayout.playerHeaderRewindMediaButton.setVisibility(View.VISIBLE); bind.playerHeaderLayout.playerHeaderRewindMediaButton.setVisibility(View.VISIBLE);

View file

@ -27,6 +27,7 @@ import com.cappielloantonio.play.R;
import com.cappielloantonio.play.databinding.InnerFragmentPlayerControllerBinding; import com.cappielloantonio.play.databinding.InnerFragmentPlayerControllerBinding;
import com.cappielloantonio.play.model.Media; import com.cappielloantonio.play.model.Media;
import com.cappielloantonio.play.service.MediaService; import com.cappielloantonio.play.service.MediaService;
import com.cappielloantonio.play.subsonic.models.Child;
import com.cappielloantonio.play.ui.activity.MainActivity; import com.cappielloantonio.play.ui.activity.MainActivity;
import com.cappielloantonio.play.ui.dialog.RatingDialog; import com.cappielloantonio.play.ui.dialog.RatingDialog;
import com.cappielloantonio.play.ui.fragment.pager.PlayerControllerHorizontalPager; import com.cappielloantonio.play.ui.fragment.pager.PlayerControllerHorizontalPager;
@ -155,7 +156,7 @@ public class PlayerControllerFragment extends Fragment {
private void setMediaInfo(MediaMetadata mediaMetadata) { private void setMediaInfo(MediaMetadata mediaMetadata) {
if (mediaMetadata.extras != null) { if (mediaMetadata.extras != null) {
String extension = mediaMetadata.extras.getString("extension", "Unknown format"); String extension = mediaMetadata.extras.getString("suffix", "Unknown format");
String bitrate = mediaMetadata.extras.getInt("bitrate", 0) != 0 ? mediaMetadata.extras.getInt("bitrate", 0) + "kbps" : "Original"; String bitrate = mediaMetadata.extras.getInt("bitrate", 0) != 0 ? mediaMetadata.extras.getInt("bitrate", 0) + "kbps" : "Original";
playerMediaExtension.setText(extension); playerMediaExtension.setText(extension);
@ -190,7 +191,7 @@ public class PlayerControllerFragment extends Fragment {
initPlaybackSpeedButton(mediaBrowser); initPlaybackSpeedButton(mediaBrowser);
if (mediaBrowser.getMediaMetadata().extras != null) { if (mediaBrowser.getMediaMetadata().extras != null) {
switch (mediaBrowser.getMediaMetadata().extras.getString("mediaType", Media.MEDIA_TYPE_MUSIC)) { switch (mediaBrowser.getMediaMetadata().extras.getString("type", Media.MEDIA_TYPE_MUSIC)) {
case Media.MEDIA_TYPE_PODCAST: case Media.MEDIA_TYPE_PODCAST:
bind.getRoot().setShowShuffleButton(false); bind.getRoot().setShowShuffleButton(false);
bind.getRoot().setShowRewindButton(true); bind.getRoot().setShowRewindButton(true);
@ -239,7 +240,7 @@ public class PlayerControllerFragment extends Fragment {
private void initMediaListenable() { private void initMediaListenable() {
playerBottomSheetViewModel.getLiveMedia().observe(getViewLifecycleOwner(), media -> { playerBottomSheetViewModel.getLiveMedia().observe(getViewLifecycleOwner(), media -> {
if (media != null) { if (media != null) {
buttonFavorite.setChecked(Boolean.TRUE.equals(media.getStarred())); buttonFavorite.setChecked(media.getStarred() != null);
buttonFavorite.setOnClickListener(v -> playerBottomSheetViewModel.setFavorite(requireContext(), media)); buttonFavorite.setOnClickListener(v -> playerBottomSheetViewModel.setFavorite(requireContext(), media));
buttonFavorite.setOnLongClickListener(v -> { buttonFavorite.setOnLongClickListener(v -> {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();

View file

@ -34,6 +34,8 @@ import com.paulrybitskyi.persistentsearchview.adapters.model.SuggestionItem;
import com.paulrybitskyi.persistentsearchview.listeners.OnSuggestionChangeListener; import com.paulrybitskyi.persistentsearchview.listeners.OnSuggestionChangeListener;
import com.paulrybitskyi.persistentsearchview.utils.SuggestionCreationUtil; import com.paulrybitskyi.persistentsearchview.utils.SuggestionCreationUtil;
import java.util.Collections;
@UnstableApi @UnstableApi
public class SearchFragment extends Fragment implements ClickCallback { public class SearchFragment extends Fragment implements ClickCallback {
private FragmentSearchBinding bind; private FragmentSearchBinding bind;
@ -179,14 +181,29 @@ public class SearchFragment extends Fragment implements ClickCallback {
private void performSearch(String query) { private void performSearch(String query) {
searchViewModel.search(query).observe(getViewLifecycleOwner(), result -> { searchViewModel.search(query).observe(getViewLifecycleOwner(), result -> {
if (bind != null) { if (bind != null) {
bind.searchArtistSector.setVisibility(!result.getArtists().isEmpty() ? View.VISIBLE : View.GONE); if (result.getArtists() != null) {
artistAdapter.setItems(result.getArtists()); bind.searchArtistSector.setVisibility(!result.getArtists().isEmpty() ? View.VISIBLE : View.GONE);
artistAdapter.setItems(result.getArtists());
} else {
artistAdapter.setItems(Collections.emptyList());
bind.searchArtistSector.setVisibility(View.GONE);
}
bind.searchAlbumSector.setVisibility(!result.getAlbums().isEmpty() ? View.VISIBLE : View.GONE); if (result.getAlbums() != null) {
albumAdapter.setItems(result.getAlbums()); bind.searchAlbumSector.setVisibility(!result.getAlbums().isEmpty() ? View.VISIBLE : View.GONE);
albumAdapter.setItems(result.getAlbums());
} else {
albumAdapter.setItems(Collections.emptyList());
bind.searchAlbumSector.setVisibility(View.GONE);
}
bind.searchSongSector.setVisibility(!result.getSongs().isEmpty() ? View.VISIBLE : View.GONE); if (result.getSongs() != null) {
songHorizontalAdapter.setItems(result.getSongs()); bind.searchSongSector.setVisibility(!result.getSongs().isEmpty() ? View.VISIBLE : View.GONE);
songHorizontalAdapter.setItems(result.getSongs());
} else {
songHorizontalAdapter.setItems(Collections.emptyList());
bind.searchSongSector.setVisibility(View.GONE);
}
} }
}); });

View file

@ -10,8 +10,6 @@ import com.cappielloantonio.play.ui.fragment.PlayerQueueFragment;
import java.util.HashMap; import java.util.HashMap;
public class PlayerControllerVerticalPager extends FragmentStateAdapter { public class PlayerControllerVerticalPager extends FragmentStateAdapter {
private static final String TAG = "PlayerControllerVerticalPager";
private final HashMap<Integer, Fragment> maps; private final HashMap<Integer, Fragment> maps;
public PlayerControllerVerticalPager(@NonNull Fragment fragment) { public PlayerControllerVerticalPager(@NonNull Fragment fragment) {

View file

@ -87,7 +87,37 @@ public class MappingUtil {
boolean isDownloaded = DownloadUtil.getDownloadTracker(context).isDownloaded(MusicUtil.getDownloadUri(media.getId())); boolean isDownloaded = DownloadUtil.getDownloadTracker(context).isDownloaded(MusicUtil.getDownloadUri(media.getId()));
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelable("child", media); bundle.putString("id", media.getId());
bundle.putString("parentId", media.getParentId());
bundle.putBoolean("isDir", media.isDir());
bundle.putString("title", media.getTitle());
bundle.putString("album", media.getAlbum());
bundle.putString("artist", media.getArtist());
bundle.putInt("track", media.getTrack() != null ? media.getTrack() : 0);
bundle.putInt("year", media.getYear() != null ? media.getYear() : 0);
bundle.putString("genre", media.getGenre());
bundle.putString("coverArtId", media.getCoverArtId());
bundle.putLong("size", media.getSize() != null ? media.getSize() : 0);
bundle.putString("contentType", media.getContentType());
bundle.putString("suffix", media.getSuffix());
bundle.putString("transcodedContentType", media.getTranscodedContentType());
bundle.putString("transcodedSuffix", media.getTranscodedSuffix());
bundle.putInt("duration", media.getDuration() != null ? media.getDuration() : 0);
bundle.putInt("bitrate", media.getBitrate() != null ? media.getBitrate() : 0);
bundle.putString("path", media.getPath());
bundle.putBoolean("isVideo", media.isVideo());
bundle.putInt("userRating", media.getUserRating() != null ? media.getUserRating() : 0);
bundle.putDouble("averageRating", media.getAverageRating() != null ? media.getAverageRating() : 0);
bundle.putLong("playCount", media.getPlayCount() != null ? media.getTrack() : 0);
bundle.putInt("discNumber", media.getDiscNumber() != null ? media.getTrack() : 0);
bundle.putLong("created", media.getCreated() != null ? media.getCreated().getTime() : 0);
bundle.putLong("starred", media.getStarred() != null ? media.getStarred().getTime() : 0);
bundle.putString("albumId", media.getAlbumId());
bundle.putString("artistId", media.getArtistId());
bundle.putString("type", media.getType());
bundle.putLong("bookmarkPosition", media.getBookmarkPosition() != null ? media.getBookmarkPosition() : 0);
bundle.putInt("originalWidth", media.getOriginalWidth() != null ? media.getOriginalWidth() : 0);
bundle.putInt("originalHeight", media.getOriginalHeight() != null ? media.getOriginalHeight() : 0);
return new MediaItem.Builder() return new MediaItem.Builder()
.setMediaId(media.getId()) .setMediaId(media.getId())

View file

@ -10,6 +10,7 @@ import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.interfaces.MediaCallback; import com.cappielloantonio.play.interfaces.MediaCallback;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.AlbumID3; import com.cappielloantonio.play.subsonic.models.AlbumID3;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
@ -59,18 +60,18 @@ public class AlbumCatalogueViewModel extends AndroidViewModel {
App.getSubsonicClientInstance(context, false) App.getSubsonicClientInstance(context, false)
.getAlbumSongListClient() .getAlbumSongListClient()
.getAlbumList2("alphabeticalByName", size, offset, null, null) .getAlbumList2("alphabeticalByName", size, offset, null, null)
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull retrofit2.Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull retrofit2.Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getAlbumList2() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getAlbumList2() != null) {
List<AlbumID3> albumList = new ArrayList<>(); List<AlbumID3> albumList = new ArrayList<>();
albumList.addAll(response.body().getAlbumList2().getAlbums()); albumList.addAll(response.body().getSubsonicResponse().getAlbumList2().getAlbums());
callback.onLoadMedia(albumList); callback.onLoadMedia(albumList);
} }
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
callback.onError(new Exception(t.getMessage())); callback.onError(new Exception(t.getMessage()));
} }
}); });

View file

@ -9,6 +9,7 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.subsonic.base.ApiResponse;
import com.cappielloantonio.play.subsonic.models.ArtistID3; import com.cappielloantonio.play.subsonic.models.ArtistID3;
import com.cappielloantonio.play.subsonic.models.IndexID3; import com.cappielloantonio.play.subsonic.models.IndexID3;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
@ -34,13 +35,13 @@ public class ArtistCatalogueViewModel extends AndroidViewModel {
App.getSubsonicClientInstance(context, false) App.getSubsonicClientInstance(context, false)
.getBrowsingClient() .getBrowsingClient()
.getArtists() .getArtists()
.enqueue(new Callback<SubsonicResponse>() { .enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(@NonNull Call<SubsonicResponse> call, @NonNull retrofit2.Response<SubsonicResponse> response) { public void onResponse(@NonNull Call<ApiResponse> call, @NonNull retrofit2.Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getArtists() != null) { if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getArtists() != null) {
List<ArtistID3> artists = new ArrayList<>(); List<ArtistID3> artists = new ArrayList<>();
for (IndexID3 index : response.body().getArtists().getIndices()) { for (IndexID3 index : response.body().getSubsonicResponse().getArtists().getIndices()) {
artists.addAll(index.getArtists()); artists.addAll(index.getArtists());
} }
@ -49,7 +50,7 @@ public class ArtistCatalogueViewModel extends AndroidViewModel {
} }
@Override @Override
public void onFailure(@NonNull Call<SubsonicResponse> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
} }
}); });