Merge pull request #529 from tzugen/fix-save-playlist

Fix save playlist
This commit is contained in:
tzugen 2021-06-21 18:58:27 +02:00 committed by GitHub
commit 6fca6d918c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1449 additions and 2009 deletions

View File

@ -35,6 +35,9 @@ exceptions:
empty-blocks:
active: true
EmptyFunctionBlock:
active: true
ignoreOverridden: true
complexity:
active: true

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,5 @@
package org.moire.ultrasonic.service;
import timber.log.Timber;
import org.moire.ultrasonic.domain.MusicDirectory;
import org.moire.ultrasonic.util.LRUCache;
import org.moire.ultrasonic.util.ShufflePlayBuffer;
@ -16,6 +14,7 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import kotlin.Lazy;
import timber.log.Timber;
import static org.koin.java.KoinJavaComponent.inject;
import static org.moire.ultrasonic.domain.PlayerState.DOWNLOADING;
@ -342,7 +341,7 @@ public class Downloader
Collections.shuffle(downloadList);
if (localMediaPlayer.currentPlaying != null)
{
downloadList.remove(getCurrentPlayingIndex());
downloadList.remove(localMediaPlayer.currentPlaying);
downloadList.add(0, localMediaPlayer.currentPlaying);
}
revision++;

View File

@ -1,81 +0,0 @@
/*
This file is part of Subsonic.
Subsonic is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Subsonic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2010 (C) Sindre Mehus
*/
package org.moire.ultrasonic.util;
import android.app.Activity;
/**
* @author Sindre Mehus
*/
public abstract class SilentBackgroundTask<T> extends BackgroundTask<T>
{
public SilentBackgroundTask(Activity activity)
{
super(activity);
}
@Override
public void execute()
{
Thread thread = new Thread()
{
@Override
public void run()
{
try
{
final T result = doInBackground();
getHandler().post(new Runnable()
{
@Override
public void run()
{
done(result);
}
});
}
catch (final Throwable t)
{
getHandler().post(new Runnable()
{
@Override
public void run()
{
error(t);
}
});
}
}
};
thread.start();
}
@Override
public void updateProgress(int messageId)
{
}
@Override
public void updateProgress(String message)
{
}
}

File diff suppressed because it is too large Load Diff

View File

@ -198,7 +198,7 @@ class CachedMusicService(private val musicService: MusicService) : MusicService,
}
@Throws(Exception::class)
override fun createPlaylist(id: String, name: String, entries: List<MusicDirectory.Entry>) {
override fun createPlaylist(id: String?, name: String?, entries: List<MusicDirectory.Entry>) {
cachedPlaylists.clear()
musicService.createPlaylist(id, name, entries)
}

View File

@ -20,6 +20,7 @@ import android.os.Looper
import android.os.PowerManager
import android.os.PowerManager.PARTIAL_WAKE_LOCK
import android.os.PowerManager.WakeLock
import androidx.lifecycle.MutableLiveData
import java.io.File
import java.net.URLEncoder
import java.util.Locale
@ -29,7 +30,6 @@ import org.moire.ultrasonic.audiofx.EqualizerController
import org.moire.ultrasonic.audiofx.VisualizerController
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
import org.moire.ultrasonic.domain.PlayerState
import org.moire.ultrasonic.fragment.PlayerFragment
import org.moire.ultrasonic.util.CancellableTask
import org.moire.ultrasonic.util.Constants
import org.moire.ultrasonic.util.StreamProxy
@ -79,10 +79,12 @@ class LocalMediaPlayer(
private var proxy: StreamProxy? = null
private var bufferTask: CancellableTask? = null
private var positionCache: PositionCache? = null
private var secondaryProgress = -1
private val pm = context.getSystemService(POWER_SERVICE) as PowerManager
private val wakeLock: WakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, this.javaClass.name)
val secondaryProgress: MutableLiveData<Int> = MutableLiveData(0)
fun init() {
Thread {
Thread.currentThread().name = "MediaPlayerThread"
@ -357,7 +359,6 @@ class LocalMediaPlayer(
downloadFile.updateModificationDate()
mediaPlayer.setOnCompletionListener(null)
secondaryProgress = -1 // Ensure seeking in non StreamProxy playback works
setPlayerState(PlayerState.IDLE)
setAudioAttributes(mediaPlayer)
@ -388,28 +389,28 @@ class LocalMediaPlayer(
setPlayerState(PlayerState.PREPARING)
mediaPlayer.setOnBufferingUpdateListener { mp, percent ->
val progressBar = PlayerFragment.getProgressBar()
val song = downloadFile.song
if (percent == 100) {
mp.setOnBufferingUpdateListener(null)
}
secondaryProgress = (percent.toDouble() / 100.toDouble() * progressBar.max).toInt()
// The secondary progress is an indicator of how far the song is cached.
if (song.transcodedContentType == null && Util.getMaxBitRate() == 0) {
progressBar?.secondaryProgress = secondaryProgress
val progress = (percent.toDouble() / 100.toDouble() * playerDuration).toInt()
secondaryProgress.postValue(progress)
}
}
mediaPlayer.setOnPreparedListener {
Timber.i("Media player prepared")
setPlayerState(PlayerState.PREPARED)
val progressBar = PlayerFragment.getProgressBar()
if (progressBar != null && downloadFile.isWorkDone) {
// Populate seek bar secondary progress if we have a complete file for consistency
PlayerFragment.getProgressBar().secondaryProgress = 100 * progressBar.max
// Populate seek bar secondary progress if we have a complete file for consistency
if (downloadFile.isWorkDone) {
secondaryProgress.postValue(playerDuration)
}
synchronized(this@LocalMediaPlayer) {
if (position != 0) {
Timber.i("Restarting player from position %d", position)

View File

@ -386,12 +386,6 @@ class MediaPlayerController(
@get:Synchronized
val playerDuration: Int
get() {
if (localMediaPlayer.currentPlaying != null) {
val duration = localMediaPlayer.currentPlaying!!.song.duration
if (duration != null) {
return duration * 1000
}
}
val mediaPlayerService = runningInstance ?: return 0
return mediaPlayerService.playerDuration
}

View File

@ -73,7 +73,7 @@ interface MusicService {
fun getPlaylists(refresh: Boolean): List<Playlist>
@Throws(Exception::class)
fun createPlaylist(id: String, name: String, entries: List<MusicDirectory.Entry>)
fun createPlaylist(id: String?, name: String?, entries: List<MusicDirectory.Entry>)
@Throws(Exception::class)
fun deletePlaylist(id: String)

View File

@ -221,7 +221,7 @@ class OfflineMusicService : MusicService, KoinComponent {
@Suppress("TooGenericExceptionCaught")
@Throws(Exception::class)
override fun createPlaylist(id: String, name: String, entries: List<MusicDirectory.Entry>) {
override fun createPlaylist(id: String?, name: String?, entries: List<MusicDirectory.Entry>) {
val playlistFile =
FileUtil.getPlaylistFile(activeServerProvider.getActiveServer().name, name)
val fw = FileWriter(playlistFile)

View File

@ -295,12 +295,20 @@ open class RESTMusicService(
return response.body()!!.playlists.toDomainEntitiesList()
}
/**
* Either ID or String is required.
* ID is required when updating
* String is required when creating
*/
@Throws(Exception::class)
override fun createPlaylist(
id: String,
name: String,
id: String?,
name: String?,
entries: List<MusicDirectory.Entry>
) {
if (id == null && name == null)
throw IllegalArgumentException("Either id or name is required.")
val pSongIds: MutableList<String> = ArrayList(entries.size)
for ((id1) in entries) {

View File

@ -0,0 +1,32 @@
/*
* SilentBackgroundTask.kt
* Copyright (C) 2009-2021 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.util
import android.app.Activity
/**
* @author Sindre Mehus
*/
abstract class SilentBackgroundTask<T>(activity: Activity?) : BackgroundTask<T>(activity) {
override fun execute() {
val thread: Thread = object : Thread() {
override fun run() {
try {
val result = doInBackground()
handler.post { done(result) }
} catch (all: Throwable) {
handler.post { error(all) }
}
}
}
thread.start()
}
override fun updateProgress(messageId: Int) {}
override fun updateProgress(message: String) {}
}