Skip to content

Commit

Permalink
music: discard songs w/o volumes
Browse files Browse the repository at this point in the history
  • Loading branch information
OxygenCobalt committed Jan 1, 2024
1 parent 673629d commit 538533b
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 29 deletions.
53 changes: 25 additions & 28 deletions app/src/main/java/org/oxycblt/auxio/music/fs/MediaStoreExtractor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ interface MediaStoreExtractor {

fun close()

fun populateFileInfo(rawSong: RawSong)
fun populateFileInfo(rawSong: RawSong): Boolean

fun populateTags(rawSong: RawSong)
}
Expand All @@ -101,7 +101,7 @@ interface MediaStoreExtractor {
// instead.
Build.MANUFACTURER.equals("huawei", ignoreCase = true) ||
Build.VERSION.SDK_INT < Build.VERSION_CODES.Q ->
DataPathInterpreter.Factory(volumeManager)
Api24PathInterpreter.Factory(volumeManager)
else -> VolumePathInterpreter.Factory(volumeManager)
}

Expand Down Expand Up @@ -216,7 +216,9 @@ private class MediaStoreExtractorImpl(
) {
while (query.moveToNext()) {
val rawSong = RawSong()
query.populateFileInfo(rawSong)
if (!query.populateFileInfo(rawSong)) {
continue
}
if (cache?.populate(rawSong) == true) {
completeSongs.sendWithTimeout(rawSong)
} else {
Expand Down Expand Up @@ -260,13 +262,13 @@ private class MediaStoreExtractorImpl(

override fun close() = cursor.close()

override fun populateFileInfo(rawSong: RawSong) {
override fun populateFileInfo(rawSong: RawSong): Boolean {
rawSong.mediaStoreId = cursor.getLong(idIndex)
rawSong.dateAdded = cursor.getLong(dateAddedIndex)
rawSong.dateModified = cursor.getLong(dateModifiedIndex)
rawSong.extensionMimeType = cursor.getString(mimeTypeIndex)
rawSong.albumMediaStoreId = cursor.getLong(albumIdIndex)
pathInterpreter.populate(rawSong)
return pathInterpreter.populate(rawSong)
}

override fun populateTags(rawSong: RawSong) {
Expand Down Expand Up @@ -343,34 +345,28 @@ private class MediaStoreExtractorImpl(
}
}

private interface Interpreter {
fun populate(rawSong: RawSong)
private sealed interface PathInterpreter {
fun populate(rawSong: RawSong): Boolean

interface Factory {
val projection: Array<String>

fun wrap(cursor: Cursor): Interpreter
}
}

private sealed interface PathInterpreter : Interpreter {
interface Factory : Interpreter.Factory {
override fun wrap(cursor: Cursor): PathInterpreter
fun wrap(cursor: Cursor): PathInterpreter

fun createSelector(paths: List<Path>): Selector?

data class Selector(val template: String, val args: List<String>)
}
}

private class DataPathInterpreter(
private open class Api24PathInterpreter(
private val cursor: Cursor,
private val volumeManager: VolumeManager
) : PathInterpreter {
private val dataIndex = cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.DATA)
private val volumes = volumeManager.getVolumes()

override fun populate(rawSong: RawSong) {
override fun populate(rawSong: RawSong): Boolean {
val data = Components.parseUnix(cursor.getString(dataIndex))

// Find the volume that transforms the DATA column into a relative path. This is
Expand All @@ -379,11 +375,11 @@ private class DataPathInterpreter(
val volumePath = volume.components ?: continue
if (volumePath.contains(data)) {
rawSong.path = Path(volume, data.depth(volumePath.components.size))
return
return true
}
}

throw IllegalStateException("Could not find volume for path $data (tried: ${volumes.map { it.components }}})")
return false
}

class Factory(private val volumeManager: VolumeManager) : PathInterpreter.Factory {
Expand Down Expand Up @@ -415,7 +411,7 @@ private class DataPathInterpreter(
}

override fun wrap(cursor: Cursor): PathInterpreter =
DataPathInterpreter(cursor, volumeManager)
Api24PathInterpreter(cursor, volumeManager)
}
}

Expand All @@ -429,20 +425,17 @@ private class VolumePathInterpreter(private val cursor: Cursor, volumeManager: V
cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.RELATIVE_PATH)
private val volumes = volumeManager.getVolumes()

override fun populate(rawSong: RawSong) {
override fun populate(rawSong: RawSong): Boolean {
// Find the StorageVolume whose MediaStore name corresponds to it.
val volumeName = cursor.getString(volumeIndex)
val volume = volumes.find { it.mediaStoreName == volumeName }
if (volume == null) {
throw IllegalStateException("Could not find volume for name $volumeName")
}

val volume = volumes.find { it.mediaStoreName == volumeName } ?: return false
// Relative path does not include file name, must use DISPLAY_NAME and add it
// in manually.
val relativePath = cursor.getString(relativePathIndex)
val displayName = cursor.getString(displayNameIndex)
val components = Components.parseUnix(relativePath).child(displayName)
rawSong.path = Path(volume, components)
return true
}

class Factory(private val volumeManager: VolumeManager) : PathInterpreter.Factory {
Expand Down Expand Up @@ -493,9 +486,13 @@ private class VolumePathInterpreter(private val cursor: Cursor, volumeManager: V
}
}

private sealed interface TagInterpreter : Interpreter {
interface Factory : Interpreter.Factory {
override fun wrap(cursor: Cursor): TagInterpreter
private sealed interface TagInterpreter {
fun populate(rawSong: RawSong)

interface Factory {
val projection: Array<String>

fun wrap(cursor: Cursor): TagInterpreter
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/org/oxycblt/auxio/util/StateUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private fun Fragment.launch(
suspend fun <E> SendChannel<E>.sendWithTimeout(element: E, timeout: Long = 10000) {
try {
withTimeout(timeout) { send(element) }
} catch (e: Exception) {
} catch (e: TimeoutCancellationException) {
throw TimeoutException("Timed out sending element $element to channel: $e")
}
}
Expand Down

0 comments on commit 538533b

Please sign in to comment.