musikr: hide unstable internals
Hypothetically I'd open these up into a broader API once I can confirm they are safely extensible.
This commit is contained in:
parent
b9c8933021
commit
2ec3bbbe8c
12 changed files with 35 additions and 34 deletions
|
@ -23,12 +23,13 @@ import androidx.media3.common.util.Log
|
|||
import java.util.UUID
|
||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||
import org.oxycblt.musikr.cover.Cover
|
||||
import org.oxycblt.musikr.cover.CoverFormat
|
||||
import org.oxycblt.musikr.cover.MutableStoredCovers
|
||||
import org.oxycblt.musikr.cover.StoredCovers
|
||||
|
||||
open class RevisionedStoredCovers(private val context: Context, private val revision: UUID?) :
|
||||
StoredCovers {
|
||||
protected val inner = revision?.let { StoredCovers.at(context, "covers_$it") }
|
||||
protected val inner = revision?.let { StoredCovers.from(context, "covers_$it", CoverFormat.jpeg()) }
|
||||
|
||||
override suspend fun obtain(id: String): RevisionedCover? {
|
||||
val split = id.split('@', limit = 2)
|
||||
|
@ -43,7 +44,7 @@ open class RevisionedStoredCovers(private val context: Context, private val revi
|
|||
val storedCovers = unlikelyToBeNull(inner)
|
||||
return storedCovers.obtain(coverId)?.let { RevisionedCover(revision, it) }
|
||||
} else {
|
||||
val storedCovers = StoredCovers.at(context, "covers_$coverRevision")
|
||||
val storedCovers = StoredCovers.from(context, "covers_$coverRevision", CoverFormat.jpeg())
|
||||
return storedCovers.obtain(coverId)?.let { RevisionedCover(coverRevision, it) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,10 +22,10 @@ import org.oxycblt.musikr.cover.StoredCovers
|
|||
import org.oxycblt.musikr.fs.DeviceFile
|
||||
import org.oxycblt.musikr.pipeline.RawSong
|
||||
|
||||
interface Cache {
|
||||
suspend fun read(file: DeviceFile, storedCovers: StoredCovers): CacheResult
|
||||
abstract class Cache {
|
||||
internal abstract suspend fun read(file: DeviceFile, storedCovers: StoredCovers): CacheResult
|
||||
|
||||
suspend fun write(song: RawSong)
|
||||
internal abstract suspend fun write(song: RawSong)
|
||||
|
||||
companion object {
|
||||
fun full(db: CacheDatabase): Cache = FullCache(db.cachedSongsDao())
|
||||
|
@ -34,13 +34,13 @@ interface Cache {
|
|||
}
|
||||
}
|
||||
|
||||
sealed interface CacheResult {
|
||||
internal sealed interface CacheResult {
|
||||
data class Hit(val song: RawSong) : CacheResult
|
||||
|
||||
data class Miss(val file: DeviceFile) : CacheResult
|
||||
}
|
||||
|
||||
private class FullCache(private val cacheInfoDao: CacheInfoDao) : Cache {
|
||||
private class FullCache(private val cacheInfoDao: CacheInfoDao) : Cache() {
|
||||
override suspend fun read(file: DeviceFile, storedCovers: StoredCovers) =
|
||||
cacheInfoDao.selectSong(file.uri.toString(), file.lastModified)?.let {
|
||||
CacheResult.Hit(it.intoRawSong(file, storedCovers))
|
||||
|
@ -50,7 +50,7 @@ private class FullCache(private val cacheInfoDao: CacheInfoDao) : Cache {
|
|||
cacheInfoDao.updateSong(CachedSong.fromRawSong(song))
|
||||
}
|
||||
|
||||
private class WriteOnlyCache(private val cacheInfoDao: CacheInfoDao) : Cache {
|
||||
private class WriteOnlyCache(private val cacheInfoDao: CacheInfoDao) : Cache() {
|
||||
override suspend fun read(file: DeviceFile, storedCovers: StoredCovers) = CacheResult.Miss(file)
|
||||
|
||||
override suspend fun write(song: RawSong) =
|
||||
|
|
|
@ -27,18 +27,18 @@ import kotlinx.coroutines.sync.Mutex
|
|||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
interface CoverFiles {
|
||||
internal interface CoverFiles {
|
||||
suspend fun find(id: String): CoverFile?
|
||||
|
||||
suspend fun write(id: String, data: ByteArray): CoverFile?
|
||||
|
||||
companion object {
|
||||
fun at(context: Context, path: String): CoverFiles =
|
||||
CoverFilesImpl(File(context.filesDir, path).also { it.mkdirs() }, CoverFormat.jpeg())
|
||||
fun at(context: Context, path: String, format: CoverFormat): CoverFiles =
|
||||
CoverFilesImpl(File(context.filesDir, path).also { it.mkdirs() }, format)
|
||||
}
|
||||
}
|
||||
|
||||
interface CoverFile {
|
||||
internal interface CoverFile {
|
||||
suspend fun open(): InputStream?
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,10 @@ import android.graphics.Bitmap
|
|||
import android.graphics.BitmapFactory
|
||||
import java.io.OutputStream
|
||||
|
||||
internal interface CoverFormat {
|
||||
val extension: String
|
||||
abstract class CoverFormat {
|
||||
internal abstract val extension: String
|
||||
|
||||
fun transcodeInto(data: ByteArray, output: OutputStream): Boolean
|
||||
internal abstract fun transcodeInto(data: ByteArray, output: OutputStream): Boolean
|
||||
|
||||
companion object {
|
||||
// Enable if perhaps you want to try other formats.
|
||||
|
@ -50,7 +50,7 @@ private class CoverFormatImpl(
|
|||
val size: Int,
|
||||
val quality: Int,
|
||||
val format: Bitmap.CompressFormat,
|
||||
) : CoverFormat {
|
||||
) : CoverFormat() {
|
||||
override fun transcodeInto(data: ByteArray, output: OutputStream) =
|
||||
BitmapFactory.Options().run {
|
||||
inJustDecodeBounds = true
|
||||
|
|
|
@ -24,8 +24,8 @@ interface StoredCovers {
|
|||
suspend fun obtain(id: String): Cover.Single?
|
||||
|
||||
companion object {
|
||||
fun at(context: Context, path: String): MutableStoredCovers =
|
||||
FileStoredCovers(CoverIdentifier.md5(), CoverFiles.at(context, path))
|
||||
fun from(context: Context, path: String, format: CoverFormat): MutableStoredCovers =
|
||||
FileStoredCovers(CoverIdentifier.md5(), CoverFiles.at(context, path, format))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ package org.oxycblt.musikr.fs
|
|||
|
||||
import android.net.Uri
|
||||
|
||||
data class DeviceFile(
|
||||
internal data class DeviceFile(
|
||||
val uri: Uri,
|
||||
val mimeType: String,
|
||||
val path: Path,
|
||||
|
|
|
@ -53,7 +53,7 @@ internal data class Metadata(
|
|||
}
|
||||
}
|
||||
|
||||
data class Properties(
|
||||
internal data class Properties(
|
||||
val mimeType: String,
|
||||
val durationMs: Long,
|
||||
val bitrateKbps: Int,
|
||||
|
|
|
@ -159,7 +159,7 @@ private class ExtractStepImpl(
|
|||
private data class FileWith<T>(val file: DeviceFile, val with: T)
|
||||
}
|
||||
|
||||
data class RawSong(
|
||||
internal data class RawSong(
|
||||
val file: DeviceFile,
|
||||
val properties: Properties,
|
||||
val tags: ParsedTags,
|
||||
|
|
|
@ -21,18 +21,18 @@ package org.oxycblt.musikr.playlist
|
|||
import org.oxycblt.musikr.Music
|
||||
import org.oxycblt.musikr.Song
|
||||
|
||||
data class PlaylistFile(
|
||||
internal data class PlaylistFile(
|
||||
val name: String,
|
||||
val songPointers: List<SongPointer>,
|
||||
val handle: PlaylistHandle
|
||||
)
|
||||
|
||||
sealed interface SongPointer {
|
||||
internal sealed interface SongPointer {
|
||||
data class UID(val uid: Music.UID) : SongPointer
|
||||
// data class Path(val options: List<Path>) : SongPointer
|
||||
}
|
||||
|
||||
interface PlaylistHandle {
|
||||
internal interface PlaylistHandle {
|
||||
val uid: Music.UID
|
||||
|
||||
suspend fun rename(name: String)
|
||||
|
|
|
@ -24,10 +24,10 @@ import org.oxycblt.musikr.playlist.PlaylistFile
|
|||
import org.oxycblt.musikr.playlist.PlaylistHandle
|
||||
import org.oxycblt.musikr.playlist.SongPointer
|
||||
|
||||
interface StoredPlaylists {
|
||||
suspend fun new(name: String, songs: List<Song>): PlaylistHandle
|
||||
abstract class StoredPlaylists {
|
||||
internal abstract suspend fun new(name: String, songs: List<Song>): PlaylistHandle
|
||||
|
||||
suspend fun read(): List<PlaylistFile>
|
||||
internal abstract suspend fun read(): List<PlaylistFile>
|
||||
|
||||
companion object {
|
||||
fun from(database: PlaylistDatabase): StoredPlaylists =
|
||||
|
@ -35,7 +35,7 @@ interface StoredPlaylists {
|
|||
}
|
||||
}
|
||||
|
||||
private class StoredPlaylistsImpl(private val playlistDao: PlaylistDao) : StoredPlaylists {
|
||||
private class StoredPlaylistsImpl(private val playlistDao: PlaylistDao) : StoredPlaylists() {
|
||||
override suspend fun new(name: String, songs: List<Song>): PlaylistHandle {
|
||||
val info = PlaylistInfo(Music.UID.auxio(Music.UID.Item.PLAYLIST), name)
|
||||
playlistDao.insertPlaylist(RawPlaylist(info, songs.map { PlaylistSong(it.uid) }))
|
||||
|
|
|
@ -41,7 +41,7 @@ import org.oxycblt.musikr.util.unlikelyToBeNull
|
|||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
interface M3U {
|
||||
abstract class M3U {
|
||||
/**
|
||||
* Reads an M3U file from the given [stream] and returns a [ImportedPlaylist] containing the
|
||||
* paths to the files listed in the M3U file.
|
||||
|
@ -51,7 +51,7 @@ interface M3U {
|
|||
* resolve relative paths.
|
||||
* @return An [ImportedPlaylist] containing the paths to the files listed in the M3U file,
|
||||
*/
|
||||
fun read(stream: InputStream, workingDirectory: Path): ImportedPlaylist?
|
||||
internal abstract fun read(stream: InputStream, workingDirectory: Path): ImportedPlaylist?
|
||||
|
||||
/**
|
||||
* Writes the given [playlist] to the given [outputStream] in the M3U format,.
|
||||
|
@ -62,7 +62,7 @@ interface M3U {
|
|||
* create relative paths to where the M3U file is assumed to be stored.
|
||||
* @param config The configuration to use when exporting the playlist.
|
||||
*/
|
||||
fun write(
|
||||
internal abstract fun write(
|
||||
playlist: Playlist,
|
||||
outputStream: OutputStream,
|
||||
workingDirectory: Path,
|
||||
|
@ -73,11 +73,11 @@ interface M3U {
|
|||
/** The mime type used for M3U files by the android system. */
|
||||
const val MIME_TYPE = "audio/x-mpegurl"
|
||||
|
||||
fun from(context: Context): M3U = M3UImpl(VolumeManager.from(context))
|
||||
internal fun from(context: Context): M3U = M3UImpl(VolumeManager.from(context))
|
||||
}
|
||||
}
|
||||
|
||||
private class M3UImpl(private val volumeManager: VolumeManager) : M3U {
|
||||
private class M3UImpl(private val volumeManager: VolumeManager) : M3U() {
|
||||
override fun read(stream: InputStream, workingDirectory: Path): ImportedPlaylist? {
|
||||
val volumes = volumeManager.getVolumes()
|
||||
val reader = BufferedReader(InputStreamReader(stream))
|
||||
|
|
|
@ -20,7 +20,7 @@ package org.oxycblt.musikr.tag.parse
|
|||
|
||||
import org.oxycblt.musikr.tag.Date
|
||||
|
||||
data class ParsedTags(
|
||||
internal data class ParsedTags(
|
||||
val durationMs: Long,
|
||||
val replayGainTrackAdjustment: Float? = null,
|
||||
val replayGainAlbumAdjustment: Float? = null,
|
||||
|
|
Loading…
Reference in a new issue