Convert all Services to Kotlin

This commit is contained in:
tzugen 2021-05-26 23:17:52 +02:00
parent 3f2daaa7ec
commit 5ac36b749b
No known key found for this signature in database
GPG Key ID: 61E9C34BC10EC930
4 changed files with 1328 additions and 1518 deletions

View File

@ -16,524 +16,470 @@
Copyright 2009 (C) Sindre Mehus Copyright 2009 (C) Sindre Mehus
*/ */
package org.moire.ultrasonic.service; package org.moire.ultrasonic.service
import android.graphics.Bitmap; import android.graphics.Bitmap
import org.koin.java.KoinJavaComponent.inject
import org.moire.ultrasonic.data.ActiveServerProvider; import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.domain.Bookmark; import org.moire.ultrasonic.domain.Bookmark
import org.moire.ultrasonic.domain.ChatMessage; import org.moire.ultrasonic.domain.ChatMessage
import org.moire.ultrasonic.domain.Genre; import org.moire.ultrasonic.domain.Genre
import org.moire.ultrasonic.domain.Indexes; import org.moire.ultrasonic.domain.Indexes
import org.moire.ultrasonic.domain.JukeboxStatus; import org.moire.ultrasonic.domain.JukeboxStatus
import org.moire.ultrasonic.domain.Lyrics; import org.moire.ultrasonic.domain.Lyrics
import org.moire.ultrasonic.domain.MusicDirectory; import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.domain.MusicFolder; import org.moire.ultrasonic.domain.MusicFolder
import org.moire.ultrasonic.domain.Playlist; import org.moire.ultrasonic.domain.Playlist
import org.moire.ultrasonic.domain.PodcastsChannel; import org.moire.ultrasonic.domain.PodcastsChannel
import org.moire.ultrasonic.domain.SearchCriteria; import org.moire.ultrasonic.domain.SearchCriteria
import org.moire.ultrasonic.domain.SearchResult; import org.moire.ultrasonic.domain.SearchResult
import org.moire.ultrasonic.domain.Share; import org.moire.ultrasonic.domain.Share
import org.moire.ultrasonic.domain.UserInfo; import org.moire.ultrasonic.domain.UserInfo
import org.moire.ultrasonic.util.Constants; import org.moire.ultrasonic.util.Constants
import org.moire.ultrasonic.util.LRUCache; import org.moire.ultrasonic.util.LRUCache
import org.moire.ultrasonic.util.TimeLimitedCache; import org.moire.ultrasonic.util.TimeLimitedCache
import org.moire.ultrasonic.util.Util; import org.moire.ultrasonic.util.Util
import java.io.InputStream
import java.io.InputStream; import java.util.concurrent.TimeUnit
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import kotlin.Lazy;
import kotlin.Pair;
import static org.koin.java.KoinJavaComponent.inject;
/** /**
* @author Sindre Mehus * @author Sindre Mehus
*/ */
public class CachedMusicService implements MusicService class CachedMusicService(private val musicService: MusicService) : MusicService {
{ private val activeServerProvider = inject(
private final Lazy<ActiveServerProvider> activeServerProvider = inject(ActiveServerProvider.class); ActiveServerProvider::class.java
)
private static final int MUSIC_DIR_CACHE_SIZE = 100; private val cachedMusicDirectories: LRUCache<String?, TimeLimitedCache<MusicDirectory?>>
private val cachedArtist: LRUCache<String?, TimeLimitedCache<MusicDirectory?>>
private final MusicService musicService; private val cachedAlbum: LRUCache<String?, TimeLimitedCache<MusicDirectory?>>
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedMusicDirectories; private val cachedUserInfo: LRUCache<String?, TimeLimitedCache<UserInfo?>>
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedArtist; private val cachedLicenseValid = TimeLimitedCache<Boolean>(120, TimeUnit.SECONDS)
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedAlbum; private val cachedIndexes = TimeLimitedCache<Indexes?>(60 * 60, TimeUnit.SECONDS)
private final LRUCache<String, TimeLimitedCache<UserInfo>> cachedUserInfo; private val cachedArtists = TimeLimitedCache<Indexes?>(60 * 60, TimeUnit.SECONDS)
private final TimeLimitedCache<Boolean> cachedLicenseValid = new TimeLimitedCache<>(120, TimeUnit.SECONDS); private val cachedPlaylists = TimeLimitedCache<List<Playlist>?>(3600, TimeUnit.SECONDS)
private final TimeLimitedCache<Indexes> cachedIndexes = new TimeLimitedCache<>(60 * 60, TimeUnit.SECONDS); private val cachedPodcastsChannels =
private final TimeLimitedCache<Indexes> cachedArtists = new TimeLimitedCache<>(60 * 60, TimeUnit.SECONDS); TimeLimitedCache<List<PodcastsChannel>>(3600, TimeUnit.SECONDS)
private final TimeLimitedCache<List<Playlist>> cachedPlaylists = new TimeLimitedCache<>(3600, TimeUnit.SECONDS); private val cachedMusicFolders =
private final TimeLimitedCache<List<PodcastsChannel>> cachedPodcastsChannels = new TimeLimitedCache<>(3600, TimeUnit.SECONDS); TimeLimitedCache<List<MusicFolder>?>(10 * 3600, TimeUnit.SECONDS)
private final TimeLimitedCache<List<MusicFolder>> cachedMusicFolders = new TimeLimitedCache<>(10 * 3600, TimeUnit.SECONDS); private val cachedGenres = TimeLimitedCache<List<Genre>?>(10 * 3600, TimeUnit.SECONDS)
private final TimeLimitedCache<List<Genre>> cachedGenres = new TimeLimitedCache<>(10 * 3600, TimeUnit.SECONDS); private var restUrl: String? = null
private var cachedMusicFolderId: String? = null
private String restUrl;
private String cachedMusicFolderId; @Throws(Exception::class)
override fun ping() {
public CachedMusicService(MusicService musicService) checkSettingsChanged()
{ musicService.ping()
this.musicService = musicService; }
cachedMusicDirectories = new LRUCache<>(MUSIC_DIR_CACHE_SIZE);
cachedArtist = new LRUCache<>(MUSIC_DIR_CACHE_SIZE); @Throws(Exception::class)
cachedAlbum = new LRUCache<>(MUSIC_DIR_CACHE_SIZE); override fun isLicenseValid(): Boolean {
cachedUserInfo = new LRUCache<>(MUSIC_DIR_CACHE_SIZE); checkSettingsChanged()
} var result = cachedLicenseValid.get()
if (result == null) {
@Override result = musicService.isLicenseValid()
public void ping() throws Exception cachedLicenseValid[result, if (result) 30L * 60L else 2L * 60L] = TimeUnit.SECONDS
{ }
checkSettingsChanged(); return result
musicService.ping(); }
}
@Throws(Exception::class)
@Override override fun getMusicFolders(refresh: Boolean): List<MusicFolder> {
public boolean isLicenseValid() throws Exception checkSettingsChanged()
{ if (refresh) {
checkSettingsChanged(); cachedMusicFolders.clear()
Boolean result = cachedLicenseValid.get(); }
if (result == null)
{ val cache = cachedMusicFolders.get()
result = musicService.isLicenseValid(); if (cache != null) return cache
cachedLicenseValid.set(result, result ? 30L * 60L : 2L * 60L, TimeUnit.SECONDS);
} val result = musicService.getMusicFolders(refresh)
return result; cachedMusicFolders.set(result)
}
return result
@Override }
public List<MusicFolder> getMusicFolders(boolean refresh) throws Exception
{ @Throws(Exception::class)
checkSettingsChanged(); override fun getIndexes(musicFolderId: String?, refresh: Boolean): Indexes {
if (refresh) checkSettingsChanged()
{ if (refresh) {
cachedMusicFolders.clear(); cachedIndexes.clear()
} cachedMusicFolders.clear()
List<MusicFolder> result = cachedMusicFolders.get(); cachedMusicDirectories.clear()
if (result == null) }
{ var result = cachedIndexes.get()
result = musicService.getMusicFolders(refresh); if (result == null) {
cachedMusicFolders.set(result); result = musicService.getIndexes(musicFolderId, refresh)
} cachedIndexes.set(result)
return result; }
} return result
}
@Override
public Indexes getIndexes(String musicFolderId, boolean refresh) throws Exception @Throws(Exception::class)
{ override fun getArtists(refresh: Boolean): Indexes {
checkSettingsChanged(); checkSettingsChanged()
if (refresh) if (refresh) {
{ cachedArtists.clear()
cachedIndexes.clear(); }
cachedMusicFolders.clear(); var result = cachedArtists.get()
cachedMusicDirectories.clear(); if (result == null) {
} result = musicService.getArtists(refresh)
Indexes result = cachedIndexes.get(); cachedArtists.set(result)
if (result == null) }
{ return result
result = musicService.getIndexes(musicFolderId, refresh); }
cachedIndexes.set(result);
} @Throws(Exception::class)
return result; override fun getMusicDirectory(id: String, name: String?, refresh: Boolean): MusicDirectory {
} checkSettingsChanged()
var cache = if (refresh) null else cachedMusicDirectories[id]
@Override var dir = cache?.get()
public Indexes getArtists(boolean refresh) throws Exception if (dir == null) {
{ dir = musicService.getMusicDirectory(id, name, refresh)
checkSettingsChanged(); cache = TimeLimitedCache(
if (refresh) Util.getDirectoryCacheTime().toLong(), TimeUnit.SECONDS
{ )
cachedArtists.clear(); cache.set(dir)
} cachedMusicDirectories.put(id, cache)
Indexes result = cachedArtists.get(); }
if (result == null) return dir
{ }
result = musicService.getArtists(refresh);
cachedArtists.set(result); @Throws(Exception::class)
} override fun getArtist(id: String, name: String?, refresh: Boolean): MusicDirectory {
return result; checkSettingsChanged()
} var cache = if (refresh) null else cachedArtist[id]
var dir = cache?.get()
@Override if (dir == null) {
public MusicDirectory getMusicDirectory(String id, String name, boolean refresh) throws Exception dir = musicService.getArtist(id, name, refresh)
{ cache = TimeLimitedCache(
checkSettingsChanged(); Util.getDirectoryCacheTime().toLong(), TimeUnit.SECONDS
TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedMusicDirectories.get(id); )
cache.set(dir)
MusicDirectory dir = cache == null ? null : cache.get(); cachedArtist.put(id, cache)
}
if (dir == null) return dir
{ }
dir = musicService.getMusicDirectory(id, name, refresh);
cache = new TimeLimitedCache<>(Util.getDirectoryCacheTime(), TimeUnit.SECONDS); @Throws(Exception::class)
cache.set(dir); override fun getAlbum(id: String, name: String?, refresh: Boolean): MusicDirectory {
cachedMusicDirectories.put(id, cache); checkSettingsChanged()
} var cache = if (refresh) null else cachedAlbum[id]
return dir; var dir = cache?.get()
} if (dir == null) {
dir = musicService.getAlbum(id, name, refresh)
@Override cache = TimeLimitedCache(
public MusicDirectory getArtist(String id, String name, boolean refresh) throws Exception Util.getDirectoryCacheTime().toLong(), TimeUnit.SECONDS
{ )
checkSettingsChanged(); cache.set(dir)
TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedArtist.get(id); cachedAlbum.put(id, cache)
MusicDirectory dir = cache == null ? null : cache.get(); }
if (dir == null) return dir
{ }
dir = musicService.getArtist(id, name, refresh);
cache = new TimeLimitedCache<>(Util.getDirectoryCacheTime(), TimeUnit.SECONDS); @Throws(Exception::class)
cache.set(dir); override fun search(criteria: SearchCriteria): SearchResult? {
cachedArtist.put(id, cache); return musicService.search(criteria)
} }
return dir;
} @Throws(Exception::class)
override fun getPlaylist(id: String, name: String): MusicDirectory {
@Override return musicService.getPlaylist(id, name)
public MusicDirectory getAlbum(String id, String name, boolean refresh) throws Exception }
{
checkSettingsChanged(); @Throws(Exception::class)
TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedAlbum.get(id); override fun getPodcastsChannels(refresh: Boolean): List<PodcastsChannel> {
MusicDirectory dir = cache == null ? null : cache.get(); checkSettingsChanged()
if (dir == null) var result = if (refresh) null else cachedPodcastsChannels.get()
{ if (result == null) {
dir = musicService.getAlbum(id, name, refresh); result = musicService.getPodcastsChannels(refresh)
cache = new TimeLimitedCache<>(Util.getDirectoryCacheTime(), TimeUnit.SECONDS); cachedPodcastsChannels.set(result)
cache.set(dir); }
cachedAlbum.put(id, cache); return result
} }
return dir;
} @Throws(Exception::class)
override fun getPodcastEpisodes(podcastChannelId: String?): MusicDirectory? {
@Override return musicService.getPodcastEpisodes(podcastChannelId)
public SearchResult search(SearchCriteria criteria) throws Exception }
{
return musicService.search(criteria); @Throws(Exception::class)
} override fun getPlaylists(refresh: Boolean): List<Playlist> {
checkSettingsChanged()
@Override var result = if (refresh) null else cachedPlaylists.get()
public MusicDirectory getPlaylist(String id, String name) throws Exception if (result == null) {
{ result = musicService.getPlaylists(refresh)
return musicService.getPlaylist(id, name); cachedPlaylists.set(result)
} }
return result
@Override }
public List<PodcastsChannel> getPodcastsChannels(boolean refresh) throws Exception {
checkSettingsChanged(); @Throws(Exception::class)
List<PodcastsChannel> result = refresh ? null : cachedPodcastsChannels.get(); override fun createPlaylist(id: String, name: String, entries: List<MusicDirectory.Entry>) {
if (result == null) cachedPlaylists.clear()
{ musicService.createPlaylist(id, name, entries)
result = musicService.getPodcastsChannels(refresh); }
cachedPodcastsChannels.set(result);
} @Throws(Exception::class)
return result; override fun deletePlaylist(id: String) {
} musicService.deletePlaylist(id)
}
@Override
public MusicDirectory getPodcastEpisodes(String podcastChannelId) throws Exception { @Throws(Exception::class)
return musicService.getPodcastEpisodes(podcastChannelId); override fun updatePlaylist(id: String, name: String?, comment: String?, pub: Boolean) {
} musicService.updatePlaylist(id, name, comment, pub)
}
@Override @Throws(Exception::class)
public List<Playlist> getPlaylists(boolean refresh) throws Exception override fun getLyrics(artist: String, title: String): Lyrics? {
{ return musicService.getLyrics(artist, title)
checkSettingsChanged(); }
List<Playlist> result = refresh ? null : cachedPlaylists.get();
if (result == null) @Throws(Exception::class)
{ override fun scrobble(id: String, submission: Boolean) {
result = musicService.getPlaylists(refresh); musicService.scrobble(id, submission)
cachedPlaylists.set(result); }
}
return result; @Throws(Exception::class)
} override fun getAlbumList(
type: String,
@Override size: Int,
public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries) throws Exception offset: Int,
{ musicFolderId: String?
cachedPlaylists.clear(); ): MusicDirectory {
musicService.createPlaylist(id, name, entries); return musicService.getAlbumList(type, size, offset, musicFolderId)
} }
@Override @Throws(Exception::class)
public void deletePlaylist(String id) throws Exception override fun getAlbumList2(
{ type: String,
musicService.deletePlaylist(id); size: Int,
} offset: Int,
musicFolderId: String?
@Override ): MusicDirectory {
public void updatePlaylist(String id, String name, String comment, boolean pub) throws Exception return musicService.getAlbumList2(type, size, offset, musicFolderId)
{ }
musicService.updatePlaylist(id, name, comment, pub);
} @Throws(Exception::class)
override fun getRandomSongs(size: Int): MusicDirectory {
@Override return musicService.getRandomSongs(size)
public Lyrics getLyrics(String artist, String title) throws Exception }
{
return musicService.getLyrics(artist, title); @Throws(Exception::class)
} override fun getStarred(): SearchResult = musicService.getStarred()
@Override @Throws(Exception::class)
public void scrobble(String id, boolean submission) throws Exception override fun getStarred2(): SearchResult = musicService.getStarred2()
{
musicService.scrobble(id, submission); @Throws(Exception::class)
} override fun getCoverArt(
entry: MusicDirectory.Entry?,
@Override size: Int,
public MusicDirectory getAlbumList(String type, int size, int offset, String musicFolderId) throws Exception saveToFile: Boolean,
{ highQuality: Boolean
return musicService.getAlbumList(type, size, offset, musicFolderId); ): Bitmap? {
} return musicService.getCoverArt(entry, size, saveToFile, highQuality)
}
@Override
public MusicDirectory getAlbumList2(String type, int size, int offset, String musicFolderId) throws Exception @Throws(Exception::class)
{ override fun getDownloadInputStream(
return musicService.getAlbumList2(type, size, offset, musicFolderId); song: MusicDirectory.Entry,
} offset: Long,
maxBitrate: Int
@Override ): Pair<InputStream, Boolean> {
public MusicDirectory getRandomSongs(int size) throws Exception return musicService.getDownloadInputStream(song, offset, maxBitrate)
{ }
return musicService.getRandomSongs(size);
} @Throws(Exception::class)
override fun getVideoUrl(id: String, useFlash: Boolean): String? {
@Override return musicService.getVideoUrl(id, useFlash)
public SearchResult getStarred() throws Exception }
{
return musicService.getStarred(); @Throws(Exception::class)
} override fun updateJukeboxPlaylist(ids: List<String>?): JukeboxStatus {
return musicService.updateJukeboxPlaylist(ids)
@Override }
public SearchResult getStarred2() throws Exception
{ @Throws(Exception::class)
return musicService.getStarred2(); override fun skipJukebox(index: Int, offsetSeconds: Int): JukeboxStatus {
} return musicService.skipJukebox(index, offsetSeconds)
}
@Override
public Bitmap getCoverArt(MusicDirectory.Entry entry, int size, boolean saveToFile, boolean highQuality) throws Exception @Throws(Exception::class)
{ override fun stopJukebox(): JukeboxStatus {
return musicService.getCoverArt(entry, size, saveToFile, highQuality); return musicService.stopJukebox()
} }
@Override @Throws(Exception::class)
public Pair<InputStream, Boolean> getDownloadInputStream(MusicDirectory.Entry song, long offset, int maxBitrate) throws Exception override fun startJukebox(): JukeboxStatus {
{ return musicService.startJukebox()
return musicService.getDownloadInputStream(song, offset, maxBitrate); }
}
@Throws(Exception::class)
@Override override fun getJukeboxStatus(): JukeboxStatus = musicService.getJukeboxStatus()
public String getVideoUrl(String id, boolean useFlash) throws Exception
{ @Throws(Exception::class)
return musicService.getVideoUrl(id, useFlash); override fun setJukeboxGain(gain: Float): JukeboxStatus {
} return musicService.setJukeboxGain(gain)
}
@Override
public JukeboxStatus updateJukeboxPlaylist(List<String> ids) throws Exception private fun checkSettingsChanged() {
{ val newUrl = activeServerProvider.value.getRestUrl(null)
return musicService.updateJukeboxPlaylist(ids); val newFolderId = activeServerProvider.value.getActiveServer().musicFolderId
} if (!Util.equals(newUrl, restUrl) || !Util.equals(cachedMusicFolderId, newFolderId)) {
cachedMusicFolders.clear()
@Override cachedMusicDirectories.clear()
public JukeboxStatus skipJukebox(int index, int offsetSeconds) throws Exception cachedLicenseValid.clear()
{ cachedIndexes.clear()
return musicService.skipJukebox(index, offsetSeconds); cachedPlaylists.clear()
} cachedGenres.clear()
cachedAlbum.clear()
@Override cachedArtist.clear()
public JukeboxStatus stopJukebox() throws Exception cachedUserInfo.clear()
{ restUrl = newUrl
return musicService.stopJukebox(); cachedMusicFolderId = newFolderId
} }
}
@Override
public JukeboxStatus startJukebox() throws Exception @Throws(Exception::class)
{ override fun star(id: String?, albumId: String?, artistId: String?) {
return musicService.startJukebox(); musicService.star(id, albumId, artistId)
} }
@Override @Throws(Exception::class)
public JukeboxStatus getJukeboxStatus() throws Exception override fun unstar(id: String?, albumId: String?, artistId: String?) {
{ musicService.unstar(id, albumId, artistId)
return musicService.getJukeboxStatus(); }
}
@Throws(Exception::class)
@Override override fun setRating(id: String, rating: Int) {
public JukeboxStatus setJukeboxGain(float gain) throws Exception musicService.setRating(id, rating)
{ }
return musicService.setJukeboxGain(gain);
} @Throws(Exception::class)
override fun getGenres(refresh: Boolean): List<Genre>? {
private void checkSettingsChanged() checkSettingsChanged()
{ if (refresh) {
String newUrl = activeServerProvider.getValue().getRestUrl(null); cachedGenres.clear()
String newFolderId = activeServerProvider.getValue().getActiveServer().getMusicFolderId(); }
if (!Util.equals(newUrl, restUrl) || !Util.equals(cachedMusicFolderId,newFolderId)) var result = cachedGenres.get()
{ if (result == null) {
cachedMusicFolders.clear(); result = musicService.getGenres(refresh)
cachedMusicDirectories.clear(); cachedGenres.set(result)
cachedLicenseValid.clear(); }
cachedIndexes.clear();
cachedPlaylists.clear(); val sorted = result?.toMutableList()
cachedGenres.clear(); sorted?.sortWith { genre, genre2 ->
cachedAlbum.clear(); genre.name.compareTo(
cachedArtist.clear(); genre2.name,
cachedUserInfo.clear(); ignoreCase = true
restUrl = newUrl; )
cachedMusicFolderId = newFolderId; }
} return sorted
} }
@Override @Throws(Exception::class)
public void star(String id, String albumId, String artistId) throws Exception override fun getSongsByGenre(genre: String, count: Int, offset: Int): MusicDirectory {
{ return musicService.getSongsByGenre(genre, count, offset)
musicService.star(id, albumId, artistId); }
}
@Throws(Exception::class)
@Override override fun getShares(refresh: Boolean): List<Share> {
public void unstar(String id, String albumId, String artistId) throws Exception return musicService.getShares(refresh)
{ }
musicService.unstar(id, albumId, artistId);
} @Throws(Exception::class)
override fun getChatMessages(since: Long?): List<ChatMessage?>? {
@Override return musicService.getChatMessages(since)
public void setRating(String id, int rating) throws Exception }
{
musicService.setRating(id, rating); @Throws(Exception::class)
} override fun addChatMessage(message: String) {
musicService.addChatMessage(message)
@Override }
public List<Genre> getGenres(boolean refresh) throws Exception
{ @Throws(Exception::class)
checkSettingsChanged(); override fun getBookmarks(): List<Bookmark?>? = musicService.getBookmarks()
if (refresh)
{ @Throws(Exception::class)
cachedGenres.clear(); override fun deleteBookmark(id: String) {
} musicService.deleteBookmark(id)
List<Genre> result = cachedGenres.get(); }
if (result == null) @Throws(Exception::class)
{ override fun createBookmark(id: String, position: Int) {
result = musicService.getGenres(refresh); musicService.createBookmark(id, position)
cachedGenres.set(result); }
}
@Throws(Exception::class)
Collections.sort(result, new Comparator<Genre>() override fun getVideos(refresh: Boolean): MusicDirectory? {
{ checkSettingsChanged()
@Override var cache =
public int compare(Genre genre, Genre genre2) if (refresh) null else cachedMusicDirectories[Constants.INTENT_EXTRA_NAME_VIDEOS]
{ var dir = cache?.get()
return genre.getName().compareToIgnoreCase(genre2.getName()); if (dir == null) {
} dir = musicService.getVideos(refresh)
}); cache = TimeLimitedCache(
Util.getDirectoryCacheTime().toLong(), TimeUnit.SECONDS
return result; )
} cache.set(dir)
cachedMusicDirectories.put(Constants.INTENT_EXTRA_NAME_VIDEOS, cache)
@Override }
public MusicDirectory getSongsByGenre(String genre, int count, int offset) throws Exception return dir
{ }
return musicService.getSongsByGenre(genre, count, offset);
} @Throws(Exception::class)
override fun getUser(username: String): UserInfo {
@Override checkSettingsChanged()
public List<Share> getShares(boolean refresh) throws Exception var cache = cachedUserInfo[username]
{ var userInfo = cache?.get()
return musicService.getShares(refresh); if (userInfo == null) {
} userInfo = musicService.getUser(username)
cache = TimeLimitedCache(
@Override Util.getDirectoryCacheTime().toLong(), TimeUnit.SECONDS
public List<ChatMessage> getChatMessages(Long since) throws Exception )
{ cache.set(userInfo)
return musicService.getChatMessages(since); cachedUserInfo.put(username, cache)
} }
return userInfo
@Override }
public void addChatMessage(String message) throws Exception
{ @Throws(Exception::class)
musicService.addChatMessage(message); override fun createShare(
} ids: List<String>,
description: String?,
@Override expires: Long?
public List<Bookmark> getBookmarks() throws Exception ): List<Share> {
{ return musicService.createShare(ids, description, expires)
return musicService.getBookmarks(); }
}
@Throws(Exception::class)
@Override override fun deleteShare(id: String) {
public void deleteBookmark(String id) throws Exception musicService.deleteShare(id)
{ }
musicService.deleteBookmark(id);
} @Throws(Exception::class)
override fun updateShare(id: String, description: String?, expires: Long?) {
@Override musicService.updateShare(id, description, expires)
public void createBookmark(String id, int position) throws Exception }
{
musicService.createBookmark(id, position); @Throws(Exception::class)
} override fun getAvatar(
username: String?,
@Override size: Int,
public MusicDirectory getVideos(boolean refresh) throws Exception saveToFile: Boolean,
{ highQuality: Boolean
checkSettingsChanged(); ): Bitmap? {
TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedMusicDirectories.get(Constants.INTENT_EXTRA_NAME_VIDEOS); return musicService.getAvatar(username, size, saveToFile, highQuality)
}
MusicDirectory dir = cache == null ? null : cache.get();
companion object {
if (dir == null) private const val MUSIC_DIR_CACHE_SIZE = 100
{ }
dir = musicService.getVideos(refresh);
cache = new TimeLimitedCache<>(Util.getDirectoryCacheTime(), TimeUnit.SECONDS); init {
cache.set(dir); cachedMusicDirectories = LRUCache(MUSIC_DIR_CACHE_SIZE)
cachedMusicDirectories.put(Constants.INTENT_EXTRA_NAME_VIDEOS, cache); cachedArtist = LRUCache(MUSIC_DIR_CACHE_SIZE)
} cachedAlbum = LRUCache(MUSIC_DIR_CACHE_SIZE)
cachedUserInfo = LRUCache(MUSIC_DIR_CACHE_SIZE)
return dir; }
} }
@Override
public UserInfo getUser(String username) throws Exception
{
checkSettingsChanged();
TimeLimitedCache<UserInfo> cache = cachedUserInfo.get(username);
UserInfo userInfo = cache == null ? null : cache.get();
if (userInfo == null)
{
userInfo = musicService.getUser(username);
cache = new TimeLimitedCache<>(Util.getDirectoryCacheTime(), TimeUnit.SECONDS);
cache.set(userInfo);
cachedUserInfo.put(username, cache);
}
return userInfo;
}
@Override
public List<Share> createShare(List<String> ids, String description, Long expires) throws Exception
{
return musicService.createShare(ids, description, expires);
}
@Override
public void deleteShare(String id) throws Exception
{
musicService.deleteShare(id);
}
@Override
public void updateShare(String id, String description, Long expires) throws Exception
{
musicService.updateShare(id, description, expires);
}
@Override
public Bitmap getAvatar(String username, int size, boolean saveToFile, boolean highQuality) throws Exception
{
return musicService.getAvatar(username, size, saveToFile, highQuality);
}
}

View File

@ -1,151 +1,192 @@
/* /*
This file is part of Subsonic. * MusicService.kt
* Copyright (C) 2009-2021 Ultrasonic developers
Subsonic is free software: you can redistribute it and/or modify *
it under the terms of the GNU General Public License as published by * Distributed under terms of the GNU GPLv3 license.
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Subsonic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009 (C) Sindre Mehus
*/ */
package org.moire.ultrasonic.service; package org.moire.ultrasonic.service
import android.graphics.Bitmap; import android.graphics.Bitmap
import org.moire.ultrasonic.domain.Bookmark
import org.moire.ultrasonic.domain.ChatMessage
import org.moire.ultrasonic.domain.Genre
import org.moire.ultrasonic.domain.Indexes
import org.moire.ultrasonic.domain.JukeboxStatus
import org.moire.ultrasonic.domain.Lyrics
import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.domain.MusicFolder
import org.moire.ultrasonic.domain.Playlist
import org.moire.ultrasonic.domain.PodcastsChannel
import org.moire.ultrasonic.domain.SearchCriteria
import org.moire.ultrasonic.domain.SearchResult
import org.moire.ultrasonic.domain.Share
import org.moire.ultrasonic.domain.UserInfo
import java.io.InputStream
import org.moire.ultrasonic.domain.Bookmark; interface MusicService {
import org.moire.ultrasonic.domain.ChatMessage; @Throws(Exception::class)
import org.moire.ultrasonic.domain.Genre; fun ping()
import org.moire.ultrasonic.domain.Indexes;
import org.moire.ultrasonic.domain.JukeboxStatus;
import org.moire.ultrasonic.domain.Lyrics;
import org.moire.ultrasonic.domain.MusicDirectory;
import org.moire.ultrasonic.domain.MusicFolder;
import org.moire.ultrasonic.domain.Playlist;
import org.moire.ultrasonic.domain.PodcastsChannel;
import org.moire.ultrasonic.domain.SearchCriteria;
import org.moire.ultrasonic.domain.SearchResult;
import org.moire.ultrasonic.domain.Share;
import org.moire.ultrasonic.domain.UserInfo;
import java.io.InputStream; @Throws(Exception::class)
import java.util.List; fun isLicenseValid(): Boolean
import kotlin.Pair; @Throws(Exception::class)
fun getGenres(refresh: Boolean): List<Genre>?
/** @Throws(Exception::class)
* @author Sindre Mehus fun star(id: String?, albumId: String?, artistId: String?)
*/
public interface MusicService
{
void ping() throws Exception; @Throws(Exception::class)
fun unstar(id: String?, albumId: String?, artistId: String?)
boolean isLicenseValid() throws Exception; @Throws(Exception::class)
fun setRating(id: String, rating: Int)
List<Genre> getGenres(boolean refresh) throws Exception; @Throws(Exception::class)
fun getMusicFolders(refresh: Boolean): List<MusicFolder>
void star(String id, String albumId, String artistId) throws Exception; @Throws(Exception::class)
fun getIndexes(musicFolderId: String?, refresh: Boolean): Indexes
void unstar(String id, String albumId, String artistId) throws Exception; @Throws(Exception::class)
fun getArtists(refresh: Boolean): Indexes
void setRating(String id, int rating) throws Exception; @Throws(Exception::class)
fun getMusicDirectory(id: String, name: String?, refresh: Boolean): MusicDirectory
List<MusicFolder> getMusicFolders(boolean refresh) throws Exception; @Throws(Exception::class)
fun getArtist(id: String, name: String?, refresh: Boolean): MusicDirectory
Indexes getIndexes(String musicFolderId, boolean refresh) throws Exception; @Throws(Exception::class)
fun getAlbum(id: String, name: String?, refresh: Boolean): MusicDirectory
Indexes getArtists(boolean refresh) throws Exception; @Throws(Exception::class)
fun search(criteria: SearchCriteria): SearchResult?
MusicDirectory getMusicDirectory(String id, String name, boolean refresh) throws Exception; @Throws(Exception::class)
fun getPlaylist(id: String, name: String): MusicDirectory
MusicDirectory getArtist(String id, String name, boolean refresh) throws Exception; @Throws(Exception::class)
fun getPodcastsChannels(refresh: Boolean): List<PodcastsChannel>
MusicDirectory getAlbum(String id, String name, boolean refresh) throws Exception; @Throws(Exception::class)
fun getPlaylists(refresh: Boolean): List<Playlist>
SearchResult search(SearchCriteria criteria) throws Exception; @Throws(Exception::class)
fun createPlaylist(id: String, name: String, entries: List<MusicDirectory.Entry>)
MusicDirectory getPlaylist(String id, String name) throws Exception; @Throws(Exception::class)
fun deletePlaylist(id: String)
List<PodcastsChannel> getPodcastsChannels(boolean refresh) throws Exception; @Throws(Exception::class)
fun updatePlaylist(id: String, name: String?, comment: String?, pub: Boolean)
List<Playlist> getPlaylists(boolean refresh) throws Exception; @Throws(Exception::class)
fun getLyrics(artist: String, title: String): Lyrics?
void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries) throws Exception; @Throws(Exception::class)
fun scrobble(id: String, submission: Boolean)
void deletePlaylist(String id) throws Exception; @Throws(Exception::class)
fun getAlbumList(type: String, size: Int, offset: Int, musicFolderId: String?): MusicDirectory
void updatePlaylist(String id, String name, String comment, boolean pub) throws Exception; @Throws(Exception::class)
fun getAlbumList2(
type: String,
size: Int,
offset: Int,
musicFolderId: String?
): MusicDirectory
Lyrics getLyrics(String artist, String title) throws Exception; @Throws(Exception::class)
fun getRandomSongs(size: Int): MusicDirectory
void scrobble(String id, boolean submission) throws Exception; @Throws(Exception::class)
fun getSongsByGenre(genre: String, count: Int, offset: Int): MusicDirectory
MusicDirectory getAlbumList(String type, int size, int offset, String musicFolderId) throws Exception; @Throws(Exception::class)
fun getStarred(): SearchResult
MusicDirectory getAlbumList2(String type, int size, int offset, String musicFolderId) throws Exception; @Throws(Exception::class)
fun getStarred2(): SearchResult
MusicDirectory getRandomSongs(int size) throws Exception; @Throws(Exception::class)
fun getCoverArt(
entry: MusicDirectory.Entry?,
size: Int,
saveToFile: Boolean,
highQuality: Boolean
): Bitmap?
MusicDirectory getSongsByGenre(String genre, int count, int offset) throws Exception; @Throws(Exception::class)
fun getAvatar(username: String?, size: Int, saveToFile: Boolean, highQuality: Boolean): Bitmap?
SearchResult getStarred() throws Exception; /**
* Return response [InputStream] and a [Boolean] that indicates if this response is
* partial.
*/
@Throws(Exception::class)
fun getDownloadInputStream(
song: MusicDirectory.Entry,
offset: Long,
maxBitrate: Int
): Pair<InputStream, Boolean>
SearchResult getStarred2() throws Exception; // TODO: Refactor and remove this call (see RestMusicService implementation)
@Throws(Exception::class)
fun getVideoUrl(id: String, useFlash: Boolean): String?
Bitmap getCoverArt(MusicDirectory.Entry entry, int size, boolean saveToFile, boolean highQuality) throws Exception; @Throws(Exception::class)
fun updateJukeboxPlaylist(ids: List<String>?): JukeboxStatus
Bitmap getAvatar(String username, int size, boolean saveToFile, boolean highQuality) throws Exception; @Throws(Exception::class)
fun skipJukebox(index: Int, offsetSeconds: Int): JukeboxStatus
/** @Throws(Exception::class)
* Return response {@link InputStream} and a {@link Boolean} that indicates if this response is fun stopJukebox(): JukeboxStatus
* partial.
*/
Pair<InputStream, Boolean> getDownloadInputStream(MusicDirectory.Entry song, long offset, int maxBitrate) throws Exception;
// TODO: Refactor and remove this call (see RestMusicService implementation) @Throws(Exception::class)
String getVideoUrl(String id, boolean useFlash) throws Exception; fun startJukebox(): JukeboxStatus
JukeboxStatus updateJukeboxPlaylist(List<String> ids) throws Exception; @Throws(Exception::class)
fun getJukeboxStatus(): JukeboxStatus
JukeboxStatus skipJukebox(int index, int offsetSeconds) throws Exception; @Throws(Exception::class)
fun setJukeboxGain(gain: Float): JukeboxStatus
JukeboxStatus stopJukebox() throws Exception; @Throws(Exception::class)
fun getShares(refresh: Boolean): List<Share>
JukeboxStatus startJukebox() throws Exception; @Throws(Exception::class)
fun getChatMessages(since: Long?): List<ChatMessage?>?
JukeboxStatus getJukeboxStatus() throws Exception; @Throws(Exception::class)
fun addChatMessage(message: String)
JukeboxStatus setJukeboxGain(float gain) throws Exception; @Throws(Exception::class)
fun getBookmarks(): List<Bookmark?>?
List<Share> getShares(boolean refresh) throws Exception; @Throws(Exception::class)
fun deleteBookmark(id: String)
List<ChatMessage> getChatMessages(Long since) throws Exception; @Throws(Exception::class)
fun createBookmark(id: String, position: Int)
void addChatMessage(String message) throws Exception; @Throws(Exception::class)
fun getVideos(refresh: Boolean): MusicDirectory?
List<Bookmark> getBookmarks() throws Exception; @Throws(Exception::class)
fun getUser(username: String): UserInfo
void deleteBookmark(String id) throws Exception; @Throws(Exception::class)
fun createShare(ids: List<String>, description: String?, expires: Long?): List<Share>
void createBookmark(String id, int position) throws Exception; @Throws(Exception::class)
fun deleteShare(id: String)
MusicDirectory getVideos(boolean refresh) throws Exception; @Throws(Exception::class)
fun updateShare(id: String, description: String?, expires: Long?)
UserInfo getUser(String username) throws Exception; @Throws(Exception::class)
fun getPodcastEpisodes(podcastChannelId: String?): MusicDirectory?
List<Share> createShare(List<String> ids, String description, Long expires) throws Exception;
void deleteShare(String id) throws Exception;
void updateShare(String id, String description, Long expires) throws Exception;
MusicDirectory getPodcastEpisodes(String podcastChannelId) throws Exception;
} }

View File

@ -1,35 +1,16 @@
/* /*
This file is part of Subsonic. * OfflineException.kt
* Copyright (C) 2009-2021 Ultrasonic developers
Subsonic is free software: you can redistribute it and/or modify *
it under the terms of the GNU General Public License as published by * Distributed under terms of the GNU GPLv3 license.
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Subsonic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009 (C) Sindre Mehus
*/ */
package org.moire.ultrasonic.service; package org.moire.ultrasonic.service
/** /**
* Thrown by service methods that are not available in offline mode. * Thrown by service methods that are not available in offline mode.
*
* @author Sindre Mehus
* @version $Id$
*/ */
public class OfflineException extends Exception class OfflineException(message: String?) : Exception(message) {
{ companion object {
private static final long serialVersionUID = -4479642294747429444L; private const val serialVersionUID = -4479642294747429444L
}
public OfflineException(String message) }
{
super(message);
}
}