Skip to content

Commit

Permalink
scanners: Handle FFmpeg extractor's disappearance
Browse files Browse the repository at this point in the history
  • Loading branch information
mikooomich committed Jan 7, 2025
1 parent 7aadd62 commit 337f6cb
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 13 deletions.
2 changes: 1 addition & 1 deletion app/src/main/java/com/dd3boh/outertune/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -387,10 +387,10 @@ class MainActivity : ComponentActivity() {
// Check if the permissions for local media access
if (firstSetupPassed && localLibEnable && autoScan
&& checkSelfPermission(MEDIA_PERMISSION_LEVEL) == PackageManager.PERMISSION_GRANTED) {
val scanner = LocalMediaScanner.getScanner(this@MainActivity, scannerImpl)

// equivalent to (quick scan)
try {
val scanner = LocalMediaScanner.getScanner(this@MainActivity, scannerImpl)
val directoryStructure = scanner.scanLocal(
database,
scanPaths.split('\n'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ fun ExperimentalSettings(
onClick = {
Toast.makeText(context, "Starting migration...", Toast.LENGTH_SHORT).show()
coroutineScope.launch(Dispatchers.IO) {
val scanner = LocalMediaScanner.getScanner(context, scannerImpl)
val scanner = LocalMediaScanner.getScanner(context, ScannerImpl.TAGLIB)
Timber.tag("Settings").d("Force Migrating local artists to YTM (MANUAL TRIGGERED)")
scanner.localToRemoteArtist(database)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
Expand Down Expand Up @@ -78,6 +79,7 @@ import com.dd3boh.outertune.ui.component.SwitchPreference
import com.dd3boh.outertune.ui.utils.DEFAULT_SCAN_PATH
import com.dd3boh.outertune.ui.utils.backToMain
import com.dd3boh.outertune.ui.utils.cacheDirectoryTree
import com.dd3boh.outertune.utils.isPackageInstalled
import com.dd3boh.outertune.utils.purgeCache
import com.dd3boh.outertune.utils.rememberEnumPreference
import com.dd3boh.outertune.utils.rememberPreference
Expand All @@ -92,14 +94,6 @@ import kotlinx.coroutines.launch
import java.time.LocalDateTime
import java.time.ZoneOffset

private fun isPackageInstalled(packageName: String, packageManager: PackageManager): Boolean {
return try {
packageManager.getPackageInfo(packageName, 0)
true
} catch (e: PackageManager.NameNotFoundException) {
false
}
}

val MEDIA_PERMISSION_LEVEL =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) Manifest.permission.READ_MEDIA_AUDIO
Expand Down Expand Up @@ -341,10 +335,10 @@ fun LocalPlayerSettings(
scannerFailure = false

coroutineScope.launch(Dispatchers.IO) {
val scanner = getScanner(context, scannerImpl)
// full rescan
if (fullRescan) {
try {
val scanner = getScanner(context, scannerImpl)
val directoryStructure =
scanner.scanLocal(
database,
Expand Down Expand Up @@ -387,6 +381,7 @@ fun LocalPlayerSettings(
} else {
// quick scan
try {
val scanner = getScanner(context, scannerImpl)
val directoryStructure = scanner.scanLocal(
database,
scanPaths.split('\n'),
Expand Down Expand Up @@ -549,11 +544,24 @@ fun LocalPlayerSettings(
isPackageInstalled("wah.mikooomich.ffMetadataEx", context.packageManager)
}

// if plugin is not found, although we reset if a scan is run, ensure the user is made aware if in settings page
LaunchedEffect(isFFmpegInstalled) {
if (scannerImpl == ScannerImpl.FFMPEG_EXT && !isFFmpegInstalled) {
onScannerImplChange(ScannerImpl.TAGLIB)
}
}

EnumListPreference(
title = { Text(stringResource(R.string.scanner_type_title)) },
icon = { Icon(Icons.Rounded.Speed, null) },
selectedValue = scannerImpl,
onValueSelected = onScannerImplChange,
onValueSelected = {
if (it == ScannerImpl.FFMPEG_EXT && isFFmpegInstalled) {
onScannerImplChange(it)
} else {
Toast.makeText(context, "FFmpeg extractor not detected.", Toast.LENGTH_LONG).show()
}
},
valueText = {
when (it) {
ScannerImpl.TAGLIB -> stringResource(R.string.scanner_type_taglib)
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/com/dd3boh/outertune/utils/Utils.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.dd3boh.outertune.utils

import android.content.pm.PackageManager
import com.dd3boh.outertune.db.entities.Artist
import com.dd3boh.outertune.ui.screens.settings.NavigationTab

Expand Down Expand Up @@ -102,4 +103,16 @@ fun numberToAlpha(l: Long): String {
alphabetMap[it.digitToInt()]
}
}.joinToString("")
}

/**
* Check if a package with the specified package name is installed
*/
fun isPackageInstalled(packageName: String, packageManager: PackageManager): Boolean {
return try {
packageManager.getPackageInfo(packageName, 0)
true
} catch (e: PackageManager.NameNotFoundException) {
false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ package com.dd3boh.outertune.utils.scanners
import android.content.Context
import android.media.MediaPlayer
import android.os.Environment
import androidx.datastore.dataStore
import androidx.datastore.preferences.core.edit
import com.dd3boh.outertune.MainActivity
import com.dd3boh.outertune.constants.AutomaticScannerKey
import com.dd3boh.outertune.constants.PlayerVolumeKey
import com.dd3boh.outertune.constants.ScannerImpl
import com.dd3boh.outertune.constants.ScannerImplKey
import com.dd3boh.outertune.constants.ScannerMatchCriteria
import com.dd3boh.outertune.db.MusicDatabase
import com.dd3boh.outertune.db.entities.ArtistEntity
Expand All @@ -22,6 +28,8 @@ import com.dd3boh.outertune.ui.utils.SYNC_SCANNER
import com.dd3boh.outertune.ui.utils.cacheDirectoryTree
import com.dd3boh.outertune.ui.utils.scannerSession
import com.dd3boh.outertune.utils.closestMatch
import com.dd3boh.outertune.utils.dataStore
import com.dd3boh.outertune.utils.isPackageInstalled
import com.dd3boh.outertune.utils.reportException
import com.zionhuang.innertube.YouTube
import kotlinx.coroutines.Deferred
Expand Down Expand Up @@ -744,8 +752,24 @@ class LocalMediaScanner(val context: Context, val scannerImpl: ScannerImpl) {
* Trust me bro, it should never be null
*/
fun getScanner(context: Context, scannerImpl: ScannerImpl): LocalMediaScanner {
/*
if the FFmpeg extractor is suddenly removed and a scan is ran, reset to taglib, disable auto scanner.
we don't want to run the taglib scanner fallback if the user explicitly selected FFmpeg as differences
can muck with the song detection. Throw the error to the ui where it can be handled there
*/
val isFFmpegInstalled = isPackageInstalled("wah.mikooomich.ffMetadataEx", context.packageManager)
if (scannerImpl == ScannerImpl.FFMPEG_EXT && isFFmpegInstalled) {
runBlocking {
context.dataStore.edit { settings ->
settings[ScannerImplKey] = ScannerImpl.TAGLIB.toString()
settings[AutomaticScannerKey] = false
}
}
throw ScannerAbortException("FFmpeg extractor was selected, but the package is no longer available. Reset to taglib scanner and disabled automatic scanning")
}

if (localScanner == null) {
localScanner = LocalMediaScanner(context, scannerImpl)
localScanner = LocalMediaScanner(context, if (isFFmpegInstalled) scannerImpl else ScannerImpl.TAGLIB)
}

return localScanner!!
Expand Down

0 comments on commit 337f6cb

Please sign in to comment.