diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/PlayerFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/PlayerFragment.kt index 417af338..785ccd19 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/PlayerFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/PlayerFragment.kt @@ -1079,8 +1079,7 @@ class PlayerFragment : Player.STATE_BUFFERING -> { val downloadStatus = resources.getString( - R.string.download_playerstate_downloading, - Util.formatPercentage(progress) + R.string.download_playerstate_loading ) progressBar.secondaryProgress = progress setTitle(this@PlayerFragment, downloadStatus) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/APIDataSource.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/APIDataSource.kt index f5b652ad..0a071dbe 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/APIDataSource.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/APIDataSource.kt @@ -147,7 +147,7 @@ open class APIDataSource private constructor( val components = dataSpec.uri.toString().split('|') val id = components[0] 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? val streamResponse: StreamResponse @@ -220,7 +220,7 @@ open class APIDataSource private constructor( @Throws(HttpDataSourceException::class) 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 { readInternal(buffer, offset, length) } catch (e: IOException) { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/CachedDataSource.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/CachedDataSource.kt index e200b5f4..19789fd9 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/CachedDataSource.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/CachedDataSource.kt @@ -10,15 +10,15 @@ package org.moire.ultrasonic.playback import android.net.Uri import androidx.core.net.toUri import androidx.media3.common.C +import androidx.media3.common.PlaybackException import androidx.media3.common.util.Util import androidx.media3.datasource.BaseDataSource import androidx.media3.datasource.DataSource import androidx.media3.datasource.DataSpec -import androidx.media3.datasource.HttpDataSource -import androidx.media3.datasource.cache.CacheDataSource -import androidx.media3.datasource.cache.CacheDataSource.CacheIgnoredReason +import androidx.media3.datasource.HttpDataSource.HttpDataSourceException import java.io.IOException import java.io.InputStream +import java.io.InterruptedIOException import org.moire.ultrasonic.util.AbstractFile import org.moire.ultrasonic.util.FileUtil import org.moire.ultrasonic.util.Storage @@ -26,30 +26,13 @@ import timber.log.Timber @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class) class CachedDataSource( - private var upstreamDataSource: DataSource, - private var eventListener: EventListener? + private var upstreamDataSource: DataSource ) : BaseDataSource(false) { class Factory( private var upstreamDataSourceFactory: 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 { return createDataSourceInternal( upstreamDataSourceFactory.createDataSource() @@ -60,30 +43,11 @@ class CachedDataSource( upstreamDataSource: DataSource ): CachedDataSource { return CachedDataSource( - upstreamDataSource, - eventListener + upstreamDataSource ) } } - /** 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 bytesRead: Long = 0 private var dataSpec: DataSpec? = null @@ -94,9 +58,7 @@ class CachedDataSource( override fun open(dataSpec: DataSpec): Long { Timber.i( - "CachedDatasource: Open: %s %s %s", - dataSpec.uri, - dataSpec.position, + "CachedDatasource: Open: %s", dataSpec.toString() ) @@ -112,6 +74,8 @@ class CachedDataSource( if (cacheLength > 0) { transferInitializing(dataSpec) bytesToRead = cacheLength + transferStarted(dataSpec) + skipFully(dataSpec.position, dataSpec) return bytesToRead } @@ -120,13 +84,14 @@ class CachedDataSource( } 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) { try { readInternal(buffer, offset, length) } catch (e: IOException) { - throw HttpDataSource.HttpDataSourceException.createForIOException( - e, Util.castNonNull(dataSpec), HttpDataSource.HttpDataSourceException.TYPE_READ + throw HttpDataSourceException.createForIOException( + e, Util.castNonNull(dataSpec), HttpDataSourceException.TYPE_READ ) } } else { @@ -148,14 +113,63 @@ class CachedDataSource( } val read = Util.castNonNull(responseByteStream).read(buffer, offset, readLength) if (read == -1) { + Timber.i("CachedDatasource: EndOfInput") return C.RESULT_END_OF_INPUT } bytesRead += read.toLong() - // TODO - // bytesTransferred(read) + bytesTransferred(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, * so its important that we return the correct value here.. @@ -165,9 +179,10 @@ class CachedDataSource( } override fun close() { - Timber.i("CachedDatasource: close") + Timber.i("CachedDatasource: close %s", openedFile) if (openedFile) { openedFile = false + transferEnded() responseByteStream?.close() responseByteStream = null } @@ -193,6 +208,10 @@ class CachedDataSource( cacheFile = Storage.getFromPath(filePath)!! responseByteStream = cacheFile!!.getFileInputStream() - return cacheFile!!.getDocumentFileDescriptor("r")!!.length + val descriptor = cacheFile!!.getDocumentFileDescriptor("r") + val length = descriptor!!.length + descriptor.close() + + return length } } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/Downloader.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/Downloader.kt index 30e75bf9..967fff92 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/Downloader.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/Downloader.kt @@ -68,7 +68,8 @@ class Downloader( override fun run() { try { Timber.w("Checking Downloads") - checkDownloadsInternal() + // FIXME + // checkDownloadsInternal() } catch (all: Exception) { Timber.e(all, "checkDownloads() failed.") } finally { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt index e3978c22..fa917baf 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt @@ -298,11 +298,13 @@ class MediaPlayerController( @Synchronized fun seekTo(position: Int) { + Timber.i("SeekTo: %s", position) controller?.seekTo(position.toLong()) } @Synchronized fun seekTo(index: Int, position: Int) { + Timber.i("SeekTo: %s %s", index, position) controller?.seekTo(index, position.toLong()) } diff --git a/ultrasonic/src/main/res/values-cs/strings.xml b/ultrasonic/src/main/res/values-cs/strings.xml index 2a8c3889..e4e015e2 100644 --- a/ultrasonic/src/main/res/values-cs/strings.xml +++ b/ultrasonic/src/main/res/values-cs/strings.xml @@ -62,7 +62,6 @@ Zobrazit album Náhodně Vizualizér - Stahuji - %s Přehrávám mix Playlist úspěšně uložen. Chyba ukládání playlistu, zkuste později. diff --git a/ultrasonic/src/main/res/values-de/strings.xml b/ultrasonic/src/main/res/values-de/strings.xml index 03e25e43..efdf3aa2 100644 --- a/ultrasonic/src/main/res/values-de/strings.xml +++ b/ultrasonic/src/main/res/values-de/strings.xml @@ -76,7 +76,6 @@ Album anzeigen Mischen Grafik - Herunterladen - %s Wiedergabeliste mischen Die Wiedergabeliste wurde gespeichert Konnte die Wiedergabeliste nicht speichern, bitte später erneut versuchen. diff --git a/ultrasonic/src/main/res/values-es/strings.xml b/ultrasonic/src/main/res/values-es/strings.xml index f2f44fc8..eced3d24 100644 --- a/ultrasonic/src/main/res/values-es/strings.xml +++ b/ultrasonic/src/main/res/values-es/strings.xml @@ -76,7 +76,6 @@ Mostrar Álbum Aleatorio Visualizador - Descargando - %s Reproduciendo en modo aleatorio Lista de reproducción guardada con éxito. Fallo al guardar la lista de reproducción, por favor reinténtalo mas tarde. diff --git a/ultrasonic/src/main/res/values-fr/strings.xml b/ultrasonic/src/main/res/values-fr/strings.xml index de7d1611..111c4cd0 100644 --- a/ultrasonic/src/main/res/values-fr/strings.xml +++ b/ultrasonic/src/main/res/values-fr/strings.xml @@ -76,7 +76,6 @@ Afficher l\'album Aléatoire Visualiseur - Téléchargement - %s En lecture aléatoire Playlist enregistrée avec succès ! Échec de l\'enregistrement de la playlist, veuillez réessayer plus tard. diff --git a/ultrasonic/src/main/res/values-hu/strings.xml b/ultrasonic/src/main/res/values-hu/strings.xml index f7a43478..04e907e7 100644 --- a/ultrasonic/src/main/res/values-hu/strings.xml +++ b/ultrasonic/src/main/res/values-hu/strings.xml @@ -71,7 +71,6 @@ Ugrás az albumhoz Véletlen sorrendű Visualizer - Letöltés - %s Véletlen sorrendű Lejátszási lista mentése sikeres. Lejátszási lista mentése sikertelen, próbálja később! diff --git a/ultrasonic/src/main/res/values-it/strings.xml b/ultrasonic/src/main/res/values-it/strings.xml index e4c1ca0c..00e94efe 100644 --- a/ultrasonic/src/main/res/values-it/strings.xml +++ b/ultrasonic/src/main/res/values-it/strings.xml @@ -59,7 +59,6 @@ Visualizza Album Casuale Visualizzatore - In scaricamento - %s Riproduzione casuale Playlist salvata con successo Impossibile salvare la playlist, riprovare più tardi. diff --git a/ultrasonic/src/main/res/values-nl/strings.xml b/ultrasonic/src/main/res/values-nl/strings.xml index 7b7cc123..93101248 100644 --- a/ultrasonic/src/main/res/values-nl/strings.xml +++ b/ultrasonic/src/main/res/values-nl/strings.xml @@ -76,7 +76,6 @@ Album tonen Willekeurig Visualisatie - Bezig met downloaden - %s Bezig met willekeurig afspelen Afspeellijst is opgeslagen. Afspeellijst kan niet worden opgeslagen. Probeer het later opnieuw. diff --git a/ultrasonic/src/main/res/values-pl/strings.xml b/ultrasonic/src/main/res/values-pl/strings.xml index 459080d4..745b3d31 100644 --- a/ultrasonic/src/main/res/values-pl/strings.xml +++ b/ultrasonic/src/main/res/values-pl/strings.xml @@ -62,7 +62,6 @@ Wyświetl album Wymieszaj Efekt wizualny - Pobieranie - %s Odtwarzanie losowe Playlista została zapisana. Błąd zapisu playlisty. Proszę spróbować później. diff --git a/ultrasonic/src/main/res/values-pt-rBR/strings.xml b/ultrasonic/src/main/res/values-pt-rBR/strings.xml index 6f9098f1..7a31aba0 100644 --- a/ultrasonic/src/main/res/values-pt-rBR/strings.xml +++ b/ultrasonic/src/main/res/values-pt-rBR/strings.xml @@ -74,7 +74,6 @@ Mostrar Álbum Misturar Visualizador - Baixando - %s Tocando misturado Playlist salva com sucesso. Falha ao salvar a playlist, Tente mais tarde. diff --git a/ultrasonic/src/main/res/values-pt/strings.xml b/ultrasonic/src/main/res/values-pt/strings.xml index 43fe5bf3..f3e6b768 100644 --- a/ultrasonic/src/main/res/values-pt/strings.xml +++ b/ultrasonic/src/main/res/values-pt/strings.xml @@ -62,7 +62,6 @@ Mostrar Álbum Misturar Visualizador - Descarregando - %s Tocando misturado Playlist salva com sucesso. Falha ao salvar a playlist, Tente mais tarde. diff --git a/ultrasonic/src/main/res/values-ru/strings.xml b/ultrasonic/src/main/res/values-ru/strings.xml index 78490e76..fb6a8e12 100644 --- a/ultrasonic/src/main/res/values-ru/strings.xml +++ b/ultrasonic/src/main/res/values-ru/strings.xml @@ -76,7 +76,6 @@ Показать альбом Случайное воспроизведение Визуализатор - Загрузка - %s Игра в случайном порядке Плейлист был успешно сохранен. Не удалось сохранить плейлист, попробуйте позже. diff --git a/ultrasonic/src/main/res/values-zh-rCN/strings.xml b/ultrasonic/src/main/res/values-zh-rCN/strings.xml index 3cba252c..0431a0db 100644 --- a/ultrasonic/src/main/res/values-zh-rCN/strings.xml +++ b/ultrasonic/src/main/res/values-zh-rCN/strings.xml @@ -76,7 +76,6 @@ 显示专辑 随机 可视化 - 下载中 - %s 随机播放 已成功保存播放列表。 保存播放列表失败,请重试。 diff --git a/ultrasonic/src/main/res/values/strings.xml b/ultrasonic/src/main/res/values/strings.xml index 13260419..6b60f2ba 100644 --- a/ultrasonic/src/main/res/values/strings.xml +++ b/ultrasonic/src/main/res/values/strings.xml @@ -78,7 +78,7 @@ Shuffle mode enabled Shuffle mode disabled Visualizer - Downloading - %s + Buffering … Playing shuffle Playlist was successfully saved. Failed to save playlist, please try later.