Fix a bunch of problems with the DataSources

This commit is contained in:
tzugen 2022-04-16 00:04:52 +02:00
parent 7d33770fd6
commit 1564379bd1
No known key found for this signature in database
GPG Key ID: 61E9C34BC10EC930
18 changed files with 78 additions and 69 deletions

View File

@ -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)

View File

@ -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) {

View File

@ -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
} }
} }

View File

@ -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 {

View File

@ -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())
} }

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>