mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 17:43:32 +00:00
feat: implemented new API getLyricsBySongId for retrieving (synced) song lyrics based on song ID
This commit is contained in:
parent
b9462d7374
commit
54be869081
11 changed files with 197 additions and 0 deletions
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.cappielloantonio.tempo.repository;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.App;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.LyricsList;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class OpenRepository {
|
||||||
|
public MutableLiveData<LyricsList> getLyricsBySongId(String id) {
|
||||||
|
MutableLiveData<LyricsList> lyricsList = new MutableLiveData<>();
|
||||||
|
|
||||||
|
App.getSubsonicClientInstance(false)
|
||||||
|
.getOpenClient()
|
||||||
|
.getLyricsBySongId(id)
|
||||||
|
.enqueue(new Callback<ApiResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||||
|
if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getLyricsList() != null) {
|
||||||
|
lyricsList.setValue(response.body().getSubsonicResponse().getLyricsList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return lyricsList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import com.cappielloantonio.tempo.subsonic.api.internetradio.InternetRadioClient
|
||||||
import com.cappielloantonio.tempo.subsonic.api.mediaannotation.MediaAnnotationClient;
|
import com.cappielloantonio.tempo.subsonic.api.mediaannotation.MediaAnnotationClient;
|
||||||
import com.cappielloantonio.tempo.subsonic.api.medialibraryscanning.MediaLibraryScanningClient;
|
import com.cappielloantonio.tempo.subsonic.api.medialibraryscanning.MediaLibraryScanningClient;
|
||||||
import com.cappielloantonio.tempo.subsonic.api.mediaretrieval.MediaRetrievalClient;
|
import com.cappielloantonio.tempo.subsonic.api.mediaretrieval.MediaRetrievalClient;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.api.open.OpenClient;
|
||||||
import com.cappielloantonio.tempo.subsonic.api.playlist.PlaylistClient;
|
import com.cappielloantonio.tempo.subsonic.api.playlist.PlaylistClient;
|
||||||
import com.cappielloantonio.tempo.subsonic.api.podcast.PodcastClient;
|
import com.cappielloantonio.tempo.subsonic.api.podcast.PodcastClient;
|
||||||
import com.cappielloantonio.tempo.subsonic.api.searching.SearchingClient;
|
import com.cappielloantonio.tempo.subsonic.api.searching.SearchingClient;
|
||||||
|
|
@ -35,6 +36,7 @@ public class Subsonic {
|
||||||
private BookmarksClient bookmarksClient;
|
private BookmarksClient bookmarksClient;
|
||||||
private InternetRadioClient internetRadioClient;
|
private InternetRadioClient internetRadioClient;
|
||||||
private SharingClient sharingClient;
|
private SharingClient sharingClient;
|
||||||
|
private OpenClient openClient;
|
||||||
|
|
||||||
public Subsonic(SubsonicPreferences preferences) {
|
public Subsonic(SubsonicPreferences preferences) {
|
||||||
this.preferences = preferences;
|
this.preferences = preferences;
|
||||||
|
|
@ -128,6 +130,13 @@ public class Subsonic {
|
||||||
return sharingClient;
|
return sharingClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OpenClient getOpenClient() {
|
||||||
|
if (openClient == null) {
|
||||||
|
openClient = new OpenClient(this);
|
||||||
|
}
|
||||||
|
return openClient;
|
||||||
|
}
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
String url = preferences.getServerUrl() + "/rest/";
|
String url = preferences.getServerUrl() + "/rest/";
|
||||||
return url.replace("//rest", "/rest");
|
return url.replace("//rest", "/rest");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.cappielloantonio.tempo.subsonic.api.open;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.subsonic.RetrofitClient;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.Subsonic;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
|
||||||
|
public class OpenClient {
|
||||||
|
private static final String TAG = "OpenClient";
|
||||||
|
|
||||||
|
private final Subsonic subsonic;
|
||||||
|
private final OpenService openService;
|
||||||
|
|
||||||
|
public OpenClient(Subsonic subsonic) {
|
||||||
|
this.subsonic = subsonic;
|
||||||
|
this.openService = new RetrofitClient(subsonic).getRetrofit().create(OpenService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Call<ApiResponse> getLyricsBySongId(String id) {
|
||||||
|
Log.d(TAG, "getLyricsBySongId()");
|
||||||
|
return openService.getLyricsBySongId(subsonic.getParams(), id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.cappielloantonio.tempo.subsonic.api.open;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.GET;
|
||||||
|
import retrofit2.http.Query;
|
||||||
|
import retrofit2.http.QueryMap;
|
||||||
|
|
||||||
|
public interface OpenService {
|
||||||
|
@GET("getLyricsBySongId")
|
||||||
|
Call<ApiResponse> getLyricsBySongId(@QueryMap Map<String, String> params, @Query("id") String id);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.cappielloantonio.tempo.subsonic.models
|
||||||
|
|
||||||
|
import androidx.annotation.Keep
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
class Line {
|
||||||
|
var start: Int? = null
|
||||||
|
lateinit var value: String
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.cappielloantonio.tempo.subsonic.models
|
||||||
|
|
||||||
|
import androidx.annotation.Keep
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
class LyricsList {
|
||||||
|
var structuredLyrics: List<StructuredLyrics>? = null
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.cappielloantonio.tempo.subsonic.models
|
||||||
|
|
||||||
|
import androidx.annotation.Keep
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
class OpenSubsonicExtension {
|
||||||
|
var name: String? = null
|
||||||
|
var versions: List<Int>? = null
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.cappielloantonio.tempo.subsonic.models
|
||||||
|
|
||||||
|
import androidx.annotation.Keep
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
class StructuredLyrics {
|
||||||
|
var displayArtist: String? = null
|
||||||
|
var displayTitle: String? = null
|
||||||
|
var lang: String? = null
|
||||||
|
var offset: Int = 0
|
||||||
|
var synced: Boolean = false
|
||||||
|
var line: List<Line>? = null
|
||||||
|
}
|
||||||
|
|
@ -51,4 +51,7 @@ class SubsonicResponse {
|
||||||
var version: String? = null
|
var version: String? = null
|
||||||
var type: String? = null
|
var type: String? = null
|
||||||
var serverVersion: String? = null
|
var serverVersion: String? = null
|
||||||
|
var openSubsonic: Boolean? = null
|
||||||
|
var openSubsonicExtensions: List<OpenSubsonicExtension>? = null
|
||||||
|
var lyricsList: LyricsList? = null
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.cappielloantonio.tempo.util;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.OpenSubsonicExtension;
|
||||||
|
import com.google.common.reflect.TypeToken;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class OpenSubsonicExtensionsUtil {
|
||||||
|
private static List<OpenSubsonicExtension> getOpenSubsonicExtensions() {
|
||||||
|
List<OpenSubsonicExtension> extensions = null;
|
||||||
|
|
||||||
|
if (Preferences.isOpenSubsonic() && Preferences.getOpenSubsonicExtensions() != null) {
|
||||||
|
extensions = new Gson().fromJson(
|
||||||
|
Preferences.getOpenSubsonicExtensions(),
|
||||||
|
new TypeToken<List<OpenSubsonicExtension>>() {
|
||||||
|
}.getType()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OpenSubsonicExtension getOpenSubsonicExtension(String extensionName) {
|
||||||
|
if (getOpenSubsonicExtensions() == null) return null;
|
||||||
|
|
||||||
|
return getOpenSubsonicExtensions().stream().filter(openSubsonicExtension -> openSubsonicExtension.getName().equals(extensionName)).findAny().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isTranscodeOffsetExtensionAvailable() {
|
||||||
|
return getOpenSubsonicExtension("transcodeOffset") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isFormPostExtensionAvailable() {
|
||||||
|
return getOpenSubsonicExtension("formPost") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSongLyricsExtensionAvailable() {
|
||||||
|
return getOpenSubsonicExtension("songLyrics") != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
package com.cappielloantonio.tempo.util
|
package com.cappielloantonio.tempo.util
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.App
|
import com.cappielloantonio.tempo.App
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.OpenSubsonicExtension
|
||||||
|
import com.google.gson.Gson
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
object Preferences {
|
object Preferences {
|
||||||
const val THEME = "theme"
|
const val THEME = "theme"
|
||||||
|
|
@ -12,6 +17,8 @@ object Preferences {
|
||||||
private const val LOW_SECURITY = "low_security"
|
private const val LOW_SECURITY = "low_security"
|
||||||
private const val BATTERY_OPTIMIZATION = "battery_optimization"
|
private const val BATTERY_OPTIMIZATION = "battery_optimization"
|
||||||
private const val SERVER_ID = "server_id"
|
private const val SERVER_ID = "server_id"
|
||||||
|
private const val OPEN_SUBSONIC = "open_subsonic"
|
||||||
|
private const val OPEN_SUBSONIC_EXTENSIONS = "open_subsonic_extensions"
|
||||||
private const val PLAYBACK_SPEED = "playback_speed"
|
private const val PLAYBACK_SPEED = "playback_speed"
|
||||||
private const val SKIP_SILENCE = "skip_silence"
|
private const val SKIP_SILENCE = "skip_silence"
|
||||||
private const val IMAGE_CACHE_SIZE = "image_cache_size"
|
private const val IMAGE_CACHE_SIZE = "image_cache_size"
|
||||||
|
|
@ -119,6 +126,26 @@ object Preferences {
|
||||||
App.getInstance().preferences.edit().putString(SERVER_ID, serverId).apply()
|
App.getInstance().preferences.edit().putString(SERVER_ID, serverId).apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isOpenSubsonic(): Boolean {
|
||||||
|
return App.getInstance().preferences.getBoolean(OPEN_SUBSONIC, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun setOpenSubsonic(isOpenSubsonic: Boolean) {
|
||||||
|
App.getInstance().preferences.edit().putBoolean(OPEN_SUBSONIC, isOpenSubsonic).apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getOpenSubsonicExtensions(): String? {
|
||||||
|
return App.getInstance().preferences.getString(OPEN_SUBSONIC_EXTENSIONS, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun setOpenSubsonicExtensions(extension: List<OpenSubsonicExtension>) {
|
||||||
|
App.getInstance().preferences.edit().putString(OPEN_SUBSONIC_EXTENSIONS, Gson().toJson(extension)).apply()
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun askForOptimization(): Boolean {
|
fun askForOptimization(): Boolean {
|
||||||
return App.getInstance().preferences.getBoolean(BATTERY_OPTIMIZATION, true)
|
return App.getInstance().preferences.getBoolean(BATTERY_OPTIMIZATION, true)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue