Skip to content

Commit

Permalink
app: local: scanners: Move scanner code to a class
Browse files Browse the repository at this point in the history
  • Loading branch information
mikooomich committed May 24, 2024
1 parent eb2f4b9 commit 59b6b95
Show file tree
Hide file tree
Showing 9 changed files with 1,081 additions and 1,008 deletions.
16 changes: 8 additions & 8 deletions app/src/main/java/com/dd3boh/outertune/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,16 @@ import com.dd3boh.outertune.ui.screens.search.OnlineSearchScreen
import com.dd3boh.outertune.ui.screens.settings.*
import com.dd3boh.outertune.ui.theme.*
import com.dd3boh.outertune.ui.utils.appBarScrollBehavior
import com.dd3boh.outertune.ui.utils.localToRemoteArtist
import com.dd3boh.outertune.ui.utils.quickSync
import com.dd3boh.outertune.ui.utils.resetHeightOffset
import com.dd3boh.outertune.ui.utils.scanLocal
import com.dd3boh.outertune.ui.utils.unloadScanner
import com.dd3boh.outertune.utils.SyncUtils
import com.dd3boh.outertune.utils.dataStore
import com.dd3boh.outertune.utils.get
import com.dd3boh.outertune.utils.purgeCache
import com.dd3boh.outertune.utils.rememberEnumPreference
import com.dd3boh.outertune.utils.rememberPreference
import com.dd3boh.outertune.utils.reportException
import com.dd3boh.outertune.utils.scanners.LocalMediaScanner
import com.dd3boh.outertune.utils.scanners.LocalMediaScanner.Companion.unloadAdvancedScanner
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand Down Expand Up @@ -235,18 +233,20 @@ class MainActivity : ComponentActivity() {
val (autoScan) = rememberPreference(AutomaticScannerKey, defaultValue = true)

if (autoScan) {
val scanner = LocalMediaScanner.getScanner()

// equivalent to (quick scan)
val directoryStructure = scanLocal(this, database, ScannerImpl.MEDIASTORE).value
quickSync(
val directoryStructure = scanner.scanLocal(this, database, ScannerImpl.MEDIASTORE).value
scanner.quickSync(
database, directoryStructure.toList(), scannerSensitivity,
strictExtensions, scannerType
)
unloadScanner()
unloadAdvancedScanner()

// start artist linking job
if (lookupYtmArtists) {
CoroutineScope(Dispatchers.IO).launch {
localToRemoteArtist(database)
scanner.localToRemoteArtist(database)
}
}
purgeCache() // juuuust to be sure
Expand Down
179 changes: 179 additions & 0 deletions app/src/main/java/com/dd3boh/outertune/models/DirectoryTree.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package com.dd3boh.outertune.models

import com.dd3boh.outertune.db.entities.Song
import com.dd3boh.outertune.ui.utils.SCANNER_DEBUG
import com.dd3boh.outertune.ui.utils.sdcardRoot
import timber.log.Timber

/**
* A tree representation of local audio files
*
* @param path root directory start
*/
class DirectoryTree(path: String) {
companion object {
const val TAG = "DirectoryTree"
var directoryUID = 0
}

/**
* Directory name
*/
var currentDir = path // file name

/**
* Full parent directory path
*/
var parent: String = ""

// folder contents
var subdirs = ArrayList<DirectoryTree>()
var files = ArrayList<Song>()

val uid = directoryUID

init {
// increment uid
directoryUID++
}

/**
* Instantiate a directory tree directly
*/
constructor(path: String, files: ArrayList<Song>) : this(path) {
this.files = files
}

fun insert(path: String, song: Song) {
// println("curr path =" + path)

// add a file
if (path.indexOf('/') == -1) {
files.add(song)
if (SCANNER_DEBUG)
Timber.tag(TAG).d("Adding song with path: $path")
return
}

// there is still subdirs to process
var tmpPath = path
if (path[path.length - 1] == '/') {
tmpPath = path.substring(0, path.length - 1)
}

// the first directory before the .
val subdirPath = tmpPath.substringBefore('/')

// create subdirs if they do not exist, then insert
var existingSubdir: DirectoryTree? = null
subdirs.forEach { subdir ->
if (subdir.currentDir == subdirPath) {
existingSubdir = subdir
return@forEach
}
}

if (existingSubdir == null) {
val tree = DirectoryTree(subdirPath)
tree.parent = "$parent/$currentDir"
tree.insert(tmpPath.substringAfter('/'), song)
subdirs.add(tree)

} else {
existingSubdir!!.insert(tmpPath.substringAfter('/'), song)
}
}


/**
* Get the name of the file from full path, without any extensions
*/
private fun getFileName(path: String?): String? {
if (path == null) {
return null
}
return path.substringAfterLast('/').substringBefore('.')
}

/**
* Retrieves song object at path
*
* @return song at path, or null if it does not exist
*/
fun getSong(path: String): Song? {
Timber.tag(TAG).d("Searching for song, at path: $path")

// search for song in current dir
if (path.indexOf('/') == -1) {
val foundSong: Song = files.first { getFileName(it.song.localPath) == getFileName(path) }
Timber.tag(TAG).d("Searching for song, found?: ${foundSong.id} Name: ${foundSong.song.title}")
return foundSong
}

// there is still subdirs to process
var tmpPath = path
if (path[path.length - 1] == '/') {
tmpPath = path.substring(0, path.length - 1)
}

// the first directory before the .
val subdirPath = tmpPath.substringBefore('/')

// scan for matching subdirectory
var existingSubdir: DirectoryTree? = null
subdirs.forEach { subdir ->
if (subdir.currentDir == subdirPath) {
existingSubdir = subdir
return@forEach
}
}

// explore the subdirectory if it exists in
if (existingSubdir == null) {
return null
} else {
return existingSubdir!!.getSong(tmpPath.substringAfter('/'))
}
}


/**
* Retrieve a list of all the songs
*/
fun toList(): List<Song> {
val songs = ArrayList<Song>()

fun traverseTree(tree: DirectoryTree, result: ArrayList<Song>) {
result.addAll(tree.files)
tree.subdirs.forEach { traverseTree(it, result) }
}

traverseTree(this, songs)
return songs
}

/**
* Retrieves a modified version of this DirectoryTree.
* All folders are recognized to be top level folders
*/
fun toFlattenedTree(): DirectoryTree {
val result = DirectoryTree(sdcardRoot)
getSubdirsRecursive(this, result.subdirs)
return result
}

/**
* Crawl the directory tree, add the subdirectories with songs to the list
* @param it
* @param result
*/
private fun getSubdirsRecursive(it: DirectoryTree, result: ArrayList<DirectoryTree>) {
if (it.files.size > 0) {
result.add(DirectoryTree(it.currentDir, it.files))
}

if (it.subdirs.size > 0) {
it.subdirs.forEach { getSubdirsRecursive(it, result) }
}
}
}
11 changes: 11 additions & 0 deletions app/src/main/java/com/dd3boh/outertune/models/SongTempData.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.dd3boh.outertune.models

import com.dd3boh.outertune.db.entities.FormatEntity

/**
* For passing along song metadata
*/
data class SongTempData(
val id: String, val path: String, val title: String, val duration: Int, val artist: String?,
val artistID: String?, val album: String?, val albumID: String?, val formatEntity: FormatEntity,
)
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ import com.dd3boh.outertune.models.MediaMetadata
import com.dd3boh.outertune.playback.queues.ListQueue
import com.dd3boh.outertune.ui.menu.FolderMenu
import com.dd3boh.outertune.ui.theme.extractThemeColor
import com.dd3boh.outertune.ui.utils.DirectoryTree
import com.dd3boh.outertune.models.DirectoryTree
import com.dd3boh.outertune.ui.utils.getLocalThumbnail
import com.dd3boh.outertune.utils.joinByBullet
import com.dd3boh.outertune.utils.makeTimeString
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import com.dd3boh.outertune.extensions.toMediaItem
import com.dd3boh.outertune.ui.component.GridMenu
import com.dd3boh.outertune.ui.component.GridMenuItem
import com.dd3boh.outertune.ui.component.SongFolderItem
import com.dd3boh.outertune.ui.utils.DirectoryTree
import com.dd3boh.outertune.models.DirectoryTree

@Composable
fun FolderMenu(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,11 @@ import com.dd3boh.outertune.ui.component.PreferenceGroupTitle
import com.dd3boh.outertune.ui.component.SwitchPreference

import com.dd3boh.outertune.ui.utils.backToMain
import com.dd3boh.outertune.ui.utils.localToRemoteArtist
import com.dd3boh.outertune.ui.utils.quickSync
import com.dd3boh.outertune.ui.utils.refreshLocal
import com.dd3boh.outertune.ui.utils.scanLocal
import com.dd3boh.outertune.ui.utils.syncDB
import com.dd3boh.outertune.ui.utils.unloadScanner
import com.dd3boh.outertune.utils.purgeCache
import com.dd3boh.outertune.utils.rememberEnumPreference
import com.dd3boh.outertune.utils.rememberPreference
import com.dd3boh.outertune.utils.scanners.LocalMediaScanner.Companion.getScanner
import com.dd3boh.outertune.utils.scanners.LocalMediaScanner.Companion.unloadAdvancedScanner
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
Expand Down Expand Up @@ -177,31 +173,32 @@ fun LocalPlayerSettings(
Toast.LENGTH_SHORT
).show()
coroutineScope.launch(Dispatchers.IO) {
val scanner = getScanner()
// full rescan
if (fullRescan) {
val directoryStructure = scanLocal(context, database, scannerType).value
syncDB(database, directoryStructure.toList(), scannerSensitivity, strictExtensions, true)
unloadScanner()
val directoryStructure = scanner.scanLocal(context, database, scannerType).value
scanner.syncDB(database, directoryStructure.toList(), scannerSensitivity, strictExtensions, true)
unloadAdvancedScanner()

// start artist linking job
if (lookupYtmArtists) {
coroutineScope.launch(Dispatchers.IO) {
localToRemoteArtist(database)
scanner.localToRemoteArtist(database)
}
}
} else {
// quick scan
val directoryStructure = scanLocal(context, database, ScannerImpl.MEDIASTORE).value
quickSync(
val directoryStructure = scanner.scanLocal(context, database, ScannerImpl.MEDIASTORE).value
scanner.quickSync(
database, directoryStructure.toList(), scannerSensitivity,
strictExtensions, scannerType
)
unloadScanner()
unloadAdvancedScanner()

// start artist linking job
if (lookupYtmArtists) {
coroutineScope.launch(Dispatchers.IO) {
localToRemoteArtist(database)
scanner.localToRemoteArtist(database)
}
}
}
Expand Down
Loading

0 comments on commit 59b6b95

Please sign in to comment.