mirror of
https://gitlab.com/ultrasonic/ultrasonic.git
synced 2025-04-29 15:11:34 +03:00
Merge pull request #529 from tzugen/fix-save-playlist
Fix save playlist
This commit is contained in:
commit
6fca6d918c
@ -35,6 +35,9 @@ exceptions:
|
|||||||
|
|
||||||
empty-blocks:
|
empty-blocks:
|
||||||
active: true
|
active: true
|
||||||
|
EmptyFunctionBlock:
|
||||||
|
active: true
|
||||||
|
ignoreOverridden: true
|
||||||
|
|
||||||
complexity:
|
complexity:
|
||||||
active: true
|
active: true
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,5 @@
|
|||||||
package org.moire.ultrasonic.service;
|
package org.moire.ultrasonic.service;
|
||||||
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
import org.moire.ultrasonic.domain.MusicDirectory;
|
import org.moire.ultrasonic.domain.MusicDirectory;
|
||||||
import org.moire.ultrasonic.util.LRUCache;
|
import org.moire.ultrasonic.util.LRUCache;
|
||||||
import org.moire.ultrasonic.util.ShufflePlayBuffer;
|
import org.moire.ultrasonic.util.ShufflePlayBuffer;
|
||||||
@ -16,6 +14,7 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import kotlin.Lazy;
|
import kotlin.Lazy;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
import static org.koin.java.KoinJavaComponent.inject;
|
import static org.koin.java.KoinJavaComponent.inject;
|
||||||
import static org.moire.ultrasonic.domain.PlayerState.DOWNLOADING;
|
import static org.moire.ultrasonic.domain.PlayerState.DOWNLOADING;
|
||||||
@ -342,7 +341,7 @@ public class Downloader
|
|||||||
Collections.shuffle(downloadList);
|
Collections.shuffle(downloadList);
|
||||||
if (localMediaPlayer.currentPlaying != null)
|
if (localMediaPlayer.currentPlaying != null)
|
||||||
{
|
{
|
||||||
downloadList.remove(getCurrentPlayingIndex());
|
downloadList.remove(localMediaPlayer.currentPlaying);
|
||||||
downloadList.add(0, localMediaPlayer.currentPlaying);
|
downloadList.add(0, localMediaPlayer.currentPlaying);
|
||||||
}
|
}
|
||||||
revision++;
|
revision++;
|
||||||
|
@ -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
@ -198,7 +198,7 @@ class CachedMusicService(private val musicService: MusicService) : MusicService,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Throws(Exception::class)
|
@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()
|
cachedPlaylists.clear()
|
||||||
musicService.createPlaylist(id, name, entries)
|
musicService.createPlaylist(id, name, entries)
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import android.os.Looper
|
|||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import android.os.PowerManager.PARTIAL_WAKE_LOCK
|
import android.os.PowerManager.PARTIAL_WAKE_LOCK
|
||||||
import android.os.PowerManager.WakeLock
|
import android.os.PowerManager.WakeLock
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
@ -29,7 +30,6 @@ import org.moire.ultrasonic.audiofx.EqualizerController
|
|||||||
import org.moire.ultrasonic.audiofx.VisualizerController
|
import org.moire.ultrasonic.audiofx.VisualizerController
|
||||||
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
|
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
|
||||||
import org.moire.ultrasonic.domain.PlayerState
|
import org.moire.ultrasonic.domain.PlayerState
|
||||||
import org.moire.ultrasonic.fragment.PlayerFragment
|
|
||||||
import org.moire.ultrasonic.util.CancellableTask
|
import org.moire.ultrasonic.util.CancellableTask
|
||||||
import org.moire.ultrasonic.util.Constants
|
import org.moire.ultrasonic.util.Constants
|
||||||
import org.moire.ultrasonic.util.StreamProxy
|
import org.moire.ultrasonic.util.StreamProxy
|
||||||
@ -79,10 +79,12 @@ class LocalMediaPlayer(
|
|||||||
private var proxy: StreamProxy? = null
|
private var proxy: StreamProxy? = null
|
||||||
private var bufferTask: CancellableTask? = null
|
private var bufferTask: CancellableTask? = null
|
||||||
private var positionCache: PositionCache? = null
|
private var positionCache: PositionCache? = null
|
||||||
private var secondaryProgress = -1
|
|
||||||
private val pm = context.getSystemService(POWER_SERVICE) as PowerManager
|
private val pm = context.getSystemService(POWER_SERVICE) as PowerManager
|
||||||
private val wakeLock: WakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, this.javaClass.name)
|
private val wakeLock: WakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, this.javaClass.name)
|
||||||
|
|
||||||
|
val secondaryProgress: MutableLiveData<Int> = MutableLiveData(0)
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
Thread {
|
Thread {
|
||||||
Thread.currentThread().name = "MediaPlayerThread"
|
Thread.currentThread().name = "MediaPlayerThread"
|
||||||
@ -357,7 +359,6 @@ class LocalMediaPlayer(
|
|||||||
|
|
||||||
downloadFile.updateModificationDate()
|
downloadFile.updateModificationDate()
|
||||||
mediaPlayer.setOnCompletionListener(null)
|
mediaPlayer.setOnCompletionListener(null)
|
||||||
secondaryProgress = -1 // Ensure seeking in non StreamProxy playback works
|
|
||||||
|
|
||||||
setPlayerState(PlayerState.IDLE)
|
setPlayerState(PlayerState.IDLE)
|
||||||
setAudioAttributes(mediaPlayer)
|
setAudioAttributes(mediaPlayer)
|
||||||
@ -388,28 +389,28 @@ class LocalMediaPlayer(
|
|||||||
setPlayerState(PlayerState.PREPARING)
|
setPlayerState(PlayerState.PREPARING)
|
||||||
|
|
||||||
mediaPlayer.setOnBufferingUpdateListener { mp, percent ->
|
mediaPlayer.setOnBufferingUpdateListener { mp, percent ->
|
||||||
val progressBar = PlayerFragment.getProgressBar()
|
|
||||||
val song = downloadFile.song
|
val song = downloadFile.song
|
||||||
|
|
||||||
if (percent == 100) {
|
if (percent == 100) {
|
||||||
mp.setOnBufferingUpdateListener(null)
|
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) {
|
if (song.transcodedContentType == null && Util.getMaxBitRate() == 0) {
|
||||||
progressBar?.secondaryProgress = secondaryProgress
|
val progress = (percent.toDouble() / 100.toDouble() * playerDuration).toInt()
|
||||||
|
secondaryProgress.postValue(progress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaPlayer.setOnPreparedListener {
|
mediaPlayer.setOnPreparedListener {
|
||||||
Timber.i("Media player prepared")
|
Timber.i("Media player prepared")
|
||||||
setPlayerState(PlayerState.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
|
||||||
// Populate seek bar secondary progress if we have a complete file for consistency
|
if (downloadFile.isWorkDone) {
|
||||||
PlayerFragment.getProgressBar().secondaryProgress = 100 * progressBar.max
|
secondaryProgress.postValue(playerDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized(this@LocalMediaPlayer) {
|
synchronized(this@LocalMediaPlayer) {
|
||||||
if (position != 0) {
|
if (position != 0) {
|
||||||
Timber.i("Restarting player from position %d", position)
|
Timber.i("Restarting player from position %d", position)
|
||||||
|
@ -386,12 +386,6 @@ class MediaPlayerController(
|
|||||||
@get:Synchronized
|
@get:Synchronized
|
||||||
val playerDuration: Int
|
val playerDuration: Int
|
||||||
get() {
|
get() {
|
||||||
if (localMediaPlayer.currentPlaying != null) {
|
|
||||||
val duration = localMediaPlayer.currentPlaying!!.song.duration
|
|
||||||
if (duration != null) {
|
|
||||||
return duration * 1000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val mediaPlayerService = runningInstance ?: return 0
|
val mediaPlayerService = runningInstance ?: return 0
|
||||||
return mediaPlayerService.playerDuration
|
return mediaPlayerService.playerDuration
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ interface MusicService {
|
|||||||
fun getPlaylists(refresh: Boolean): List<Playlist>
|
fun getPlaylists(refresh: Boolean): List<Playlist>
|
||||||
|
|
||||||
@Throws(Exception::class)
|
@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)
|
@Throws(Exception::class)
|
||||||
fun deletePlaylist(id: String)
|
fun deletePlaylist(id: String)
|
||||||
|
@ -221,7 +221,7 @@ class OfflineMusicService : MusicService, KoinComponent {
|
|||||||
|
|
||||||
@Suppress("TooGenericExceptionCaught")
|
@Suppress("TooGenericExceptionCaught")
|
||||||
@Throws(Exception::class)
|
@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 =
|
val playlistFile =
|
||||||
FileUtil.getPlaylistFile(activeServerProvider.getActiveServer().name, name)
|
FileUtil.getPlaylistFile(activeServerProvider.getActiveServer().name, name)
|
||||||
val fw = FileWriter(playlistFile)
|
val fw = FileWriter(playlistFile)
|
||||||
|
@ -295,12 +295,20 @@ open class RESTMusicService(
|
|||||||
return response.body()!!.playlists.toDomainEntitiesList()
|
return response.body()!!.playlists.toDomainEntitiesList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Either ID or String is required.
|
||||||
|
* ID is required when updating
|
||||||
|
* String is required when creating
|
||||||
|
*/
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
override fun createPlaylist(
|
override fun createPlaylist(
|
||||||
id: String,
|
id: String?,
|
||||||
name: String,
|
name: String?,
|
||||||
entries: List<MusicDirectory.Entry>
|
entries: List<MusicDirectory.Entry>
|
||||||
) {
|
) {
|
||||||
|
if (id == null && name == null)
|
||||||
|
throw IllegalArgumentException("Either id or name is required.")
|
||||||
|
|
||||||
val pSongIds: MutableList<String> = ArrayList(entries.size)
|
val pSongIds: MutableList<String> = ArrayList(entries.size)
|
||||||
|
|
||||||
for ((id1) in entries) {
|
for ((id1) in entries) {
|
||||||
|
@ -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) {}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user