package link.roadio.riff.player.library import link.roadio.cuetree.CatalogView import link.roadio.cuetree.NodeKind import link.roadio.riff.userstate.ContentIds internal data class FolderAlbumContainer( val id: Long, val base: Int, val album: Int, val sources: IntArray, ) { val lookup: IntArray = sources.sortedArray() } /** Only references to producer-owned ALBM positions; no metadata parsing or regrouping. * AI-INTENT: One physical file can have several independently named ALBM views. * https://wiki.271.pics/Riff/1-1-0/catalog-consumption#fragment-containers-in-folders */ internal class CuetreeFolderContainers( snapshot: CatalogView, albums: Array, hash: (ByteArray) -> Long, ) { val records: List val byBase: Map val structuredBases: Set init { val positions = linkedMapOf, MutableList>() val structured = mutableSetOf() val bases = mutableMapOf>() fun baseSources(fragment: Int): List = bases.getOrPut(requireNotNull(snapshot.nodeParentId(fragment))) { snapshot.sources(requireNotNull(snapshot.nodeParentId(fragment))).filter { snapshot.nodeKind(it) == NodeKind.MEDIA || snapshot.nodeKind(it) == NodeKind.FAILEDL1 } } snapshot.nodes.indices .filter { snapshot.nodeKind(it) == NodeKind.FRAGMENT } .forEach { structured.addAll(baseSources(it)) } albums.forEachIndexed { album, sources -> sources.filter { snapshot.nodeKind(it) == NodeKind.FRAGMENT }.forEach { fragment -> baseSources(fragment).forEach { base -> positions.getOrPut(base to album, ::mutableListOf).add(fragment) } } } val ids = ContentIds(hash) records = positions .map { (key, sources) -> val (base, album) = key val id = ids.id("folder-album") { nullable(snapshot.nodeParentId(base)?.hi) text(snapshot.nodeSourceName(base)) long(snapshot.albumId(album)) } FolderAlbumContainer(id, base, album, sources.toIntArray()) }.associateBy { it.id } .values .sortedBy { it.id } byBase = records.indices.groupBy { records[it].base }.mapValues { it.value.toIntArray() } structuredBases = structured } fun find(id: Long): Int? = records.binarySearchBy(id) { it.id }.takeIf { it >= 0 } fun key(index: Int): String = "media-container:${records[index].id.toULong().toString(16)}" }