Fix a bunch of problems with the DataSources
This commit is contained in:
parent
7d33770fd6
commit
1564379bd1
|
@ -1079,8 +1079,7 @@ class PlayerFragment :
|
||||||
Player.STATE_BUFFERING -> {
|
Player.STATE_BUFFERING -> {
|
||||||
|
|
||||||
val downloadStatus = resources.getString(
|
val downloadStatus = resources.getString(
|
||||||
R.string.download_playerstate_downloading,
|
R.string.download_playerstate_loading
|
||||||
Util.formatPercentage(progress)
|
|
||||||
)
|
)
|
||||||
progressBar.secondaryProgress = progress
|
progressBar.secondaryProgress = progress
|
||||||
setTitle(this@PlayerFragment, downloadStatus)
|
setTitle(this@PlayerFragment, downloadStatus)
|
||||||
|
|
|
@ -147,7 +147,7 @@ open class APIDataSource private constructor(
|
||||||
val components = dataSpec.uri.toString().split('|')
|
val components = dataSpec.uri.toString().split('|')
|
||||||
val id = components[0]
|
val id = components[0]
|
||||||
val bitrate = components[1].toInt()
|
val bitrate = components[1].toInt()
|
||||||
val request = subsonicAPIClient.api.stream(id, bitrate, offset = 0)
|
val request = subsonicAPIClient.api.stream(id, bitrate, offset = dataSpec.position)
|
||||||
val response: retrofit2.Response<ResponseBody>?
|
val response: retrofit2.Response<ResponseBody>?
|
||||||
val streamResponse: StreamResponse
|
val streamResponse: StreamResponse
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ open class APIDataSource private constructor(
|
||||||
|
|
||||||
@Throws(HttpDataSourceException::class)
|
@Throws(HttpDataSourceException::class)
|
||||||
override fun read(buffer: ByteArray, offset: Int, length: Int): Int {
|
override fun read(buffer: ByteArray, offset: Int, length: Int): Int {
|
||||||
Timber.i("APIDatasource: Read: %s %s %s", buffer, offset, length)
|
Timber.d("APIDatasource: Read: %s %s", offset, length)
|
||||||
return try {
|
return try {
|
||||||
readInternal(buffer, offset, length)
|
readInternal(buffer, offset, length)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
|
|
|
@ -10,15 +10,15 @@ package org.moire.ultrasonic.playback
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.media3.common.C
|
import androidx.media3.common.C
|
||||||
|
import androidx.media3.common.PlaybackException
|
||||||
import androidx.media3.common.util.Util
|
import androidx.media3.common.util.Util
|
||||||
import androidx.media3.datasource.BaseDataSource
|
import androidx.media3.datasource.BaseDataSource
|
||||||
import androidx.media3.datasource.DataSource
|
import androidx.media3.datasource.DataSource
|
||||||
import androidx.media3.datasource.DataSpec
|
import androidx.media3.datasource.DataSpec
|
||||||
import androidx.media3.datasource.HttpDataSource
|
import androidx.media3.datasource.HttpDataSource.HttpDataSourceException
|
||||||
import androidx.media3.datasource.cache.CacheDataSource
|
|
||||||
import androidx.media3.datasource.cache.CacheDataSource.CacheIgnoredReason
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
import java.io.InterruptedIOException
|
||||||
import org.moire.ultrasonic.util.AbstractFile
|
import org.moire.ultrasonic.util.AbstractFile
|
||||||
import org.moire.ultrasonic.util.FileUtil
|
import org.moire.ultrasonic.util.FileUtil
|
||||||
import org.moire.ultrasonic.util.Storage
|
import org.moire.ultrasonic.util.Storage
|
||||||
|
@ -26,30 +26,13 @@ import timber.log.Timber
|
||||||
|
|
||||||
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
||||||
class CachedDataSource(
|
class CachedDataSource(
|
||||||
private var upstreamDataSource: DataSource,
|
private var upstreamDataSource: DataSource
|
||||||
private var eventListener: EventListener?
|
|
||||||
) : BaseDataSource(false) {
|
) : BaseDataSource(false) {
|
||||||
|
|
||||||
class Factory(
|
class Factory(
|
||||||
private var upstreamDataSourceFactory: DataSource.Factory
|
private var upstreamDataSourceFactory: DataSource.Factory
|
||||||
) : DataSource.Factory {
|
) : DataSource.Factory {
|
||||||
|
|
||||||
private var eventListener: EventListener? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {link EventListener} to which events are delivered.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* The default is `null`.
|
|
||||||
*
|
|
||||||
* @param eventListener The [EventListener].
|
|
||||||
* @return This factory.
|
|
||||||
*/
|
|
||||||
fun setEventListener(eventListener: EventListener?): Factory {
|
|
||||||
this.eventListener = eventListener
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createDataSource(): CachedDataSource {
|
override fun createDataSource(): CachedDataSource {
|
||||||
return createDataSourceInternal(
|
return createDataSourceInternal(
|
||||||
upstreamDataSourceFactory.createDataSource()
|
upstreamDataSourceFactory.createDataSource()
|
||||||
|
@ -60,30 +43,11 @@ class CachedDataSource(
|
||||||
upstreamDataSource: DataSource
|
upstreamDataSource: DataSource
|
||||||
): CachedDataSource {
|
): CachedDataSource {
|
||||||
return CachedDataSource(
|
return CachedDataSource(
|
||||||
upstreamDataSource,
|
upstreamDataSource
|
||||||
eventListener
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Listener of [CacheDataSource] events. */
|
|
||||||
interface EventListener {
|
|
||||||
/**
|
|
||||||
* Called when bytes have been read from the cache.
|
|
||||||
*
|
|
||||||
* @param cacheSizeBytes Current cache size in bytes.
|
|
||||||
* @param cachedBytesRead Total bytes read from the cache since this method was last called.
|
|
||||||
*/
|
|
||||||
fun onCachedBytesRead(cacheSizeBytes: Long, cachedBytesRead: Long)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the current request ignores cache.
|
|
||||||
*
|
|
||||||
* @param reason Reason cache is bypassed.
|
|
||||||
*/
|
|
||||||
fun onCacheIgnored(reason: @CacheIgnoredReason Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var bytesToRead: Long = 0
|
private var bytesToRead: Long = 0
|
||||||
private var bytesRead: Long = 0
|
private var bytesRead: Long = 0
|
||||||
private var dataSpec: DataSpec? = null
|
private var dataSpec: DataSpec? = null
|
||||||
|
@ -94,9 +58,7 @@ class CachedDataSource(
|
||||||
|
|
||||||
override fun open(dataSpec: DataSpec): Long {
|
override fun open(dataSpec: DataSpec): Long {
|
||||||
Timber.i(
|
Timber.i(
|
||||||
"CachedDatasource: Open: %s %s %s",
|
"CachedDatasource: Open: %s",
|
||||||
dataSpec.uri,
|
|
||||||
dataSpec.position,
|
|
||||||
dataSpec.toString()
|
dataSpec.toString()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -112,6 +74,8 @@ class CachedDataSource(
|
||||||
if (cacheLength > 0) {
|
if (cacheLength > 0) {
|
||||||
transferInitializing(dataSpec)
|
transferInitializing(dataSpec)
|
||||||
bytesToRead = cacheLength
|
bytesToRead = cacheLength
|
||||||
|
transferStarted(dataSpec)
|
||||||
|
skipFully(dataSpec.position, dataSpec)
|
||||||
return bytesToRead
|
return bytesToRead
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,13 +84,14 @@ class CachedDataSource(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun read(buffer: ByteArray, offset: Int, length: Int): Int {
|
override fun read(buffer: ByteArray, offset: Int, length: Int): Int {
|
||||||
Timber.i("CachedDatasource: Read: %s %s %s", buffer, offset, length)
|
if (offset > 0 || length > 4)
|
||||||
|
Timber.d("CachedDatasource: Read: %s %s", offset, length)
|
||||||
return if (cachePath != null) {
|
return if (cachePath != null) {
|
||||||
try {
|
try {
|
||||||
readInternal(buffer, offset, length)
|
readInternal(buffer, offset, length)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
throw HttpDataSource.HttpDataSourceException.createForIOException(
|
throw HttpDataSourceException.createForIOException(
|
||||||
e, Util.castNonNull(dataSpec), HttpDataSource.HttpDataSourceException.TYPE_READ
|
e, Util.castNonNull(dataSpec), HttpDataSourceException.TYPE_READ
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,14 +113,63 @@ class CachedDataSource(
|
||||||
}
|
}
|
||||||
val read = Util.castNonNull(responseByteStream).read(buffer, offset, readLength)
|
val read = Util.castNonNull(responseByteStream).read(buffer, offset, readLength)
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
|
Timber.i("CachedDatasource: EndOfInput")
|
||||||
return C.RESULT_END_OF_INPUT
|
return C.RESULT_END_OF_INPUT
|
||||||
}
|
}
|
||||||
bytesRead += read.toLong()
|
bytesRead += read.toLong()
|
||||||
// TODO
|
bytesTransferred(read)
|
||||||
// bytesTransferred(read)
|
|
||||||
return read
|
return read
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to skip the specified number of bytes in full.
|
||||||
|
*
|
||||||
|
* @param bytesToSkip The number of bytes to skip.
|
||||||
|
* @param dataSpec The [DataSpec].
|
||||||
|
* @throws HttpDataSourceException If the thread is interrupted during the operation, or an error
|
||||||
|
* occurs while reading from the source, or if the data ended before skipping the specified
|
||||||
|
* number of bytes.
|
||||||
|
*/
|
||||||
|
@Suppress("ThrowsCount")
|
||||||
|
@Throws(HttpDataSourceException::class)
|
||||||
|
private fun skipFully(bytesToSkip: Long, dataSpec: DataSpec) {
|
||||||
|
var bytesToSkip = bytesToSkip
|
||||||
|
if (bytesToSkip == 0L) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val skipBuffer = ByteArray(4096)
|
||||||
|
try {
|
||||||
|
while (bytesToSkip > 0) {
|
||||||
|
val readLength =
|
||||||
|
bytesToSkip.coerceAtMost(skipBuffer.size.toLong()).toInt()
|
||||||
|
val read = Util.castNonNull(responseByteStream).read(skipBuffer, 0, readLength)
|
||||||
|
if (Thread.currentThread().isInterrupted) {
|
||||||
|
throw InterruptedIOException()
|
||||||
|
}
|
||||||
|
if (read == -1) {
|
||||||
|
throw HttpDataSourceException(
|
||||||
|
dataSpec,
|
||||||
|
PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE,
|
||||||
|
HttpDataSourceException.TYPE_OPEN
|
||||||
|
)
|
||||||
|
}
|
||||||
|
bytesToSkip -= read.toLong()
|
||||||
|
bytesTransferred(read)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} catch (e: IOException) {
|
||||||
|
if (e is HttpDataSourceException) {
|
||||||
|
throw e
|
||||||
|
} else {
|
||||||
|
throw HttpDataSourceException(
|
||||||
|
dataSpec,
|
||||||
|
PlaybackException.ERROR_CODE_IO_UNSPECIFIED,
|
||||||
|
HttpDataSourceException.TYPE_OPEN
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This method is called by StatsDataSource to verify that the loading succeeded,
|
* This method is called by StatsDataSource to verify that the loading succeeded,
|
||||||
* so its important that we return the correct value here..
|
* so its important that we return the correct value here..
|
||||||
|
@ -165,9 +179,10 @@ class CachedDataSource(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
Timber.i("CachedDatasource: close")
|
Timber.i("CachedDatasource: close %s", openedFile)
|
||||||
if (openedFile) {
|
if (openedFile) {
|
||||||
openedFile = false
|
openedFile = false
|
||||||
|
transferEnded()
|
||||||
responseByteStream?.close()
|
responseByteStream?.close()
|
||||||
responseByteStream = null
|
responseByteStream = null
|
||||||
}
|
}
|
||||||
|
@ -193,6 +208,10 @@ class CachedDataSource(
|
||||||
cacheFile = Storage.getFromPath(filePath)!!
|
cacheFile = Storage.getFromPath(filePath)!!
|
||||||
responseByteStream = cacheFile!!.getFileInputStream()
|
responseByteStream = cacheFile!!.getFileInputStream()
|
||||||
|
|
||||||
return cacheFile!!.getDocumentFileDescriptor("r")!!.length
|
val descriptor = cacheFile!!.getDocumentFileDescriptor("r")
|
||||||
|
val length = descriptor!!.length
|
||||||
|
descriptor.close()
|
||||||
|
|
||||||
|
return length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,8 @@ class Downloader(
|
||||||
override fun run() {
|
override fun run() {
|
||||||
try {
|
try {
|
||||||
Timber.w("Checking Downloads")
|
Timber.w("Checking Downloads")
|
||||||
checkDownloadsInternal()
|
// FIXME
|
||||||
|
// checkDownloadsInternal()
|
||||||
} catch (all: Exception) {
|
} catch (all: Exception) {
|
||||||
Timber.e(all, "checkDownloads() failed.")
|
Timber.e(all, "checkDownloads() failed.")
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -298,11 +298,13 @@ class MediaPlayerController(
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun seekTo(position: Int) {
|
fun seekTo(position: Int) {
|
||||||
|
Timber.i("SeekTo: %s", position)
|
||||||
controller?.seekTo(position.toLong())
|
controller?.seekTo(position.toLong())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun seekTo(index: Int, position: Int) {
|
fun seekTo(index: Int, position: Int) {
|
||||||
|
Timber.i("SeekTo: %s %s", index, position)
|
||||||
controller?.seekTo(index, position.toLong())
|
controller?.seekTo(index, position.toLong())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,6 @@
|
||||||
<string name="download.menu_show_album">Zobrazit album</string>
|
<string name="download.menu_show_album">Zobrazit album</string>
|
||||||
<string name="download.menu_shuffle">Náhodně</string>
|
<string name="download.menu_shuffle">Náhodně</string>
|
||||||
<string name="download.menu_visualizer">Vizualizér</string>
|
<string name="download.menu_visualizer">Vizualizér</string>
|
||||||
<string name="download.playerstate_downloading">Stahuji - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">Přehrávám mix</string>
|
<string name="download.playerstate_playing_shuffle">Přehrávám mix</string>
|
||||||
<string name="download.playlist_done">Playlist úspěšně uložen.</string>
|
<string name="download.playlist_done">Playlist úspěšně uložen.</string>
|
||||||
<string name="download.playlist_error">Chyba ukládání playlistu, zkuste později.</string>
|
<string name="download.playlist_error">Chyba ukládání playlistu, zkuste později.</string>
|
||||||
|
|
|
@ -76,7 +76,6 @@
|
||||||
<string name="download.menu_show_album">Album anzeigen</string>
|
<string name="download.menu_show_album">Album anzeigen</string>
|
||||||
<string name="download.menu_shuffle">Mischen</string>
|
<string name="download.menu_shuffle">Mischen</string>
|
||||||
<string name="download.menu_visualizer">Grafik</string>
|
<string name="download.menu_visualizer">Grafik</string>
|
||||||
<string name="download.playerstate_downloading">Herunterladen - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">Wiedergabeliste mischen</string>
|
<string name="download.playerstate_playing_shuffle">Wiedergabeliste mischen</string>
|
||||||
<string name="download.playlist_done">Die Wiedergabeliste wurde gespeichert</string>
|
<string name="download.playlist_done">Die Wiedergabeliste wurde gespeichert</string>
|
||||||
<string name="download.playlist_error">Konnte die Wiedergabeliste nicht speichern, bitte später erneut versuchen.</string>
|
<string name="download.playlist_error">Konnte die Wiedergabeliste nicht speichern, bitte später erneut versuchen.</string>
|
||||||
|
|
|
@ -76,7 +76,6 @@
|
||||||
<string name="download.menu_show_album">Mostrar Álbum</string>
|
<string name="download.menu_show_album">Mostrar Álbum</string>
|
||||||
<string name="download.menu_shuffle">Aleatorio</string>
|
<string name="download.menu_shuffle">Aleatorio</string>
|
||||||
<string name="download.menu_visualizer">Visualizador</string>
|
<string name="download.menu_visualizer">Visualizador</string>
|
||||||
<string name="download.playerstate_downloading">Descargando - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">Reproduciendo en modo aleatorio</string>
|
<string name="download.playerstate_playing_shuffle">Reproduciendo en modo aleatorio</string>
|
||||||
<string name="download.playlist_done">Lista de reproducción guardada con éxito.</string>
|
<string name="download.playlist_done">Lista de reproducción guardada con éxito.</string>
|
||||||
<string name="download.playlist_error">Fallo al guardar la lista de reproducción, por favor reinténtalo mas tarde.</string>
|
<string name="download.playlist_error">Fallo al guardar la lista de reproducción, por favor reinténtalo mas tarde.</string>
|
||||||
|
|
|
@ -76,7 +76,6 @@
|
||||||
<string name="download.menu_show_album">Afficher l\'album</string>
|
<string name="download.menu_show_album">Afficher l\'album</string>
|
||||||
<string name="download.menu_shuffle">Aléatoire</string>
|
<string name="download.menu_shuffle">Aléatoire</string>
|
||||||
<string name="download.menu_visualizer">Visualiseur</string>
|
<string name="download.menu_visualizer">Visualiseur</string>
|
||||||
<string name="download.playerstate_downloading">Téléchargement - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">En lecture aléatoire</string>
|
<string name="download.playerstate_playing_shuffle">En lecture aléatoire</string>
|
||||||
<string name="download.playlist_done">Playlist enregistrée avec succès !</string>
|
<string name="download.playlist_done">Playlist enregistrée avec succès !</string>
|
||||||
<string name="download.playlist_error">Échec de l\'enregistrement de la playlist, veuillez réessayer plus tard.</string>
|
<string name="download.playlist_error">Échec de l\'enregistrement de la playlist, veuillez réessayer plus tard.</string>
|
||||||
|
|
|
@ -71,7 +71,6 @@
|
||||||
<string name="download.menu_show_album">Ugrás az albumhoz</string>
|
<string name="download.menu_show_album">Ugrás az albumhoz</string>
|
||||||
<string name="download.menu_shuffle">Véletlen sorrendű</string>
|
<string name="download.menu_shuffle">Véletlen sorrendű</string>
|
||||||
<string name="download.menu_visualizer">Visualizer</string>
|
<string name="download.menu_visualizer">Visualizer</string>
|
||||||
<string name="download.playerstate_downloading">Letöltés - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">Véletlen sorrendű</string>
|
<string name="download.playerstate_playing_shuffle">Véletlen sorrendű</string>
|
||||||
<string name="download.playlist_done">Lejátszási lista mentése sikeres.</string>
|
<string name="download.playlist_done">Lejátszási lista mentése sikeres.</string>
|
||||||
<string name="download.playlist_error">Lejátszási lista mentése sikertelen, próbálja később!</string>
|
<string name="download.playlist_error">Lejátszási lista mentése sikertelen, próbálja később!</string>
|
||||||
|
|
|
@ -59,7 +59,6 @@
|
||||||
<string name="download.menu_show_album">Visualizza Album</string>
|
<string name="download.menu_show_album">Visualizza Album</string>
|
||||||
<string name="download.menu_shuffle">Casuale</string>
|
<string name="download.menu_shuffle">Casuale</string>
|
||||||
<string name="download.menu_visualizer">Visualizzatore</string>
|
<string name="download.menu_visualizer">Visualizzatore</string>
|
||||||
<string name="download.playerstate_downloading">In scaricamento - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">Riproduzione casuale</string>
|
<string name="download.playerstate_playing_shuffle">Riproduzione casuale</string>
|
||||||
<string name="download.playlist_done">Playlist salvata con successo </string>
|
<string name="download.playlist_done">Playlist salvata con successo </string>
|
||||||
<string name="download.playlist_error">Impossibile salvare la playlist, riprovare più tardi.</string>
|
<string name="download.playlist_error">Impossibile salvare la playlist, riprovare più tardi.</string>
|
||||||
|
|
|
@ -76,7 +76,6 @@
|
||||||
<string name="download.menu_show_album">Album tonen</string>
|
<string name="download.menu_show_album">Album tonen</string>
|
||||||
<string name="download.menu_shuffle">Willekeurig</string>
|
<string name="download.menu_shuffle">Willekeurig</string>
|
||||||
<string name="download.menu_visualizer">Visualisatie</string>
|
<string name="download.menu_visualizer">Visualisatie</string>
|
||||||
<string name="download.playerstate_downloading">Bezig met downloaden - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">Bezig met willekeurig afspelen</string>
|
<string name="download.playerstate_playing_shuffle">Bezig met willekeurig afspelen</string>
|
||||||
<string name="download.playlist_done">Afspeellijst is opgeslagen.</string>
|
<string name="download.playlist_done">Afspeellijst is opgeslagen.</string>
|
||||||
<string name="download.playlist_error">Afspeellijst kan niet worden opgeslagen. Probeer het later opnieuw.</string>
|
<string name="download.playlist_error">Afspeellijst kan niet worden opgeslagen. Probeer het later opnieuw.</string>
|
||||||
|
|
|
@ -62,7 +62,6 @@
|
||||||
<string name="download.menu_show_album">Wyświetl album</string>
|
<string name="download.menu_show_album">Wyświetl album</string>
|
||||||
<string name="download.menu_shuffle">Wymieszaj</string>
|
<string name="download.menu_shuffle">Wymieszaj</string>
|
||||||
<string name="download.menu_visualizer">Efekt wizualny</string>
|
<string name="download.menu_visualizer">Efekt wizualny</string>
|
||||||
<string name="download.playerstate_downloading">Pobieranie - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">Odtwarzanie losowe</string>
|
<string name="download.playerstate_playing_shuffle">Odtwarzanie losowe</string>
|
||||||
<string name="download.playlist_done">Playlista została zapisana.</string>
|
<string name="download.playlist_done">Playlista została zapisana.</string>
|
||||||
<string name="download.playlist_error">Błąd zapisu playlisty. Proszę spróbować później.</string>
|
<string name="download.playlist_error">Błąd zapisu playlisty. Proszę spróbować później.</string>
|
||||||
|
|
|
@ -74,7 +74,6 @@
|
||||||
<string name="download.menu_show_album">Mostrar Álbum</string>
|
<string name="download.menu_show_album">Mostrar Álbum</string>
|
||||||
<string name="download.menu_shuffle">Misturar</string>
|
<string name="download.menu_shuffle">Misturar</string>
|
||||||
<string name="download.menu_visualizer">Visualizador</string>
|
<string name="download.menu_visualizer">Visualizador</string>
|
||||||
<string name="download.playerstate_downloading">Baixando - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">Tocando misturado</string>
|
<string name="download.playerstate_playing_shuffle">Tocando misturado</string>
|
||||||
<string name="download.playlist_done">Playlist salva com sucesso.</string>
|
<string name="download.playlist_done">Playlist salva com sucesso.</string>
|
||||||
<string name="download.playlist_error">Falha ao salvar a playlist, Tente mais tarde.</string>
|
<string name="download.playlist_error">Falha ao salvar a playlist, Tente mais tarde.</string>
|
||||||
|
|
|
@ -62,7 +62,6 @@
|
||||||
<string name="download.menu_show_album">Mostrar Álbum</string>
|
<string name="download.menu_show_album">Mostrar Álbum</string>
|
||||||
<string name="download.menu_shuffle">Misturar</string>
|
<string name="download.menu_shuffle">Misturar</string>
|
||||||
<string name="download.menu_visualizer">Visualizador</string>
|
<string name="download.menu_visualizer">Visualizador</string>
|
||||||
<string name="download.playerstate_downloading">Descarregando - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">Tocando misturado</string>
|
<string name="download.playerstate_playing_shuffle">Tocando misturado</string>
|
||||||
<string name="download.playlist_done">Playlist salva com sucesso.</string>
|
<string name="download.playlist_done">Playlist salva com sucesso.</string>
|
||||||
<string name="download.playlist_error">Falha ao salvar a playlist, Tente mais tarde.</string>
|
<string name="download.playlist_error">Falha ao salvar a playlist, Tente mais tarde.</string>
|
||||||
|
|
|
@ -76,7 +76,6 @@
|
||||||
<string name="download.menu_show_album">Показать альбом</string>
|
<string name="download.menu_show_album">Показать альбом</string>
|
||||||
<string name="download.menu_shuffle">Случайное воспроизведение</string>
|
<string name="download.menu_shuffle">Случайное воспроизведение</string>
|
||||||
<string name="download.menu_visualizer">Визуализатор</string>
|
<string name="download.menu_visualizer">Визуализатор</string>
|
||||||
<string name="download.playerstate_downloading">Загрузка - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">Игра в случайном порядке</string>
|
<string name="download.playerstate_playing_shuffle">Игра в случайном порядке</string>
|
||||||
<string name="download.playlist_done">Плейлист был успешно сохранен.</string>
|
<string name="download.playlist_done">Плейлист был успешно сохранен.</string>
|
||||||
<string name="download.playlist_error">Не удалось сохранить плейлист, попробуйте позже.</string>
|
<string name="download.playlist_error">Не удалось сохранить плейлист, попробуйте позже.</string>
|
||||||
|
|
|
@ -76,7 +76,6 @@
|
||||||
<string name="download.menu_show_album">显示专辑</string>
|
<string name="download.menu_show_album">显示专辑</string>
|
||||||
<string name="download.menu_shuffle">随机</string>
|
<string name="download.menu_shuffle">随机</string>
|
||||||
<string name="download.menu_visualizer">可视化</string>
|
<string name="download.menu_visualizer">可视化</string>
|
||||||
<string name="download.playerstate_downloading">下载中 - %s</string>
|
|
||||||
<string name="download.playerstate_playing_shuffle">随机播放</string>
|
<string name="download.playerstate_playing_shuffle">随机播放</string>
|
||||||
<string name="download.playlist_done">已成功保存播放列表。</string>
|
<string name="download.playlist_done">已成功保存播放列表。</string>
|
||||||
<string name="download.playlist_error">保存播放列表失败,请重试。</string>
|
<string name="download.playlist_error">保存播放列表失败,请重试。</string>
|
||||||
|
|
|
@ -78,7 +78,7 @@
|
||||||
<string name="download.menu_shuffle_on">Shuffle mode enabled</string>
|
<string name="download.menu_shuffle_on">Shuffle mode enabled</string>
|
||||||
<string name="download.menu_shuffle_off">Shuffle mode disabled</string>
|
<string name="download.menu_shuffle_off">Shuffle mode disabled</string>
|
||||||
<string name="download.menu_visualizer">Visualizer</string>
|
<string name="download.menu_visualizer">Visualizer</string>
|
||||||
<string name="download.playerstate_downloading">Downloading - %s</string>
|
<string name="download.playerstate_loading">Buffering …</string>
|
||||||
<string name="download.playerstate_playing_shuffle">Playing shuffle</string>
|
<string name="download.playerstate_playing_shuffle">Playing shuffle</string>
|
||||||
<string name="download.playlist_done">Playlist was successfully saved.</string>
|
<string name="download.playlist_done">Playlist was successfully saved.</string>
|
||||||
<string name="download.playlist_error">Failed to save playlist, please try later.</string>
|
<string name="download.playlist_error">Failed to save playlist, please try later.</string>
|
||||||
|
|
Loading…
Reference in New Issue