Skip to content

Commit

Permalink
modify db in platform code
Browse files Browse the repository at this point in the history
  • Loading branch information
andannn committed Nov 25, 2024
1 parent 62b2691 commit 18d9810
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import com.andannn.melodify.core.database.dao.MediaLibraryDao
import com.andannn.melodify.core.syncer.model.MediaDataModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
Expand All @@ -15,7 +16,30 @@ import kotlinx.coroutines.withContext

class MediaLibraryScannerImpl(
private val app: Application,
private val mediaLibraryDao: MediaLibraryDao,
) : MediaLibraryScanner {

override suspend fun scanMediaDataAndSyncDatabase(): Unit = coroutineScope {
val musicDataDeferred = async { getAllMusicData() }
val albumDataDeferred = async { getAllAlbumData() }
val artistDataDeferred = async { getAllArtistData() }
val genreDataDeferred = async { getAllGenreData() }

val mediaData = MediaDataModel(
audioData = musicDataDeferred.await(),
albumData = albumDataDeferred.await(),
artistData = artistDataDeferred.await(),
genreData = genreDataDeferred.await(),
)

mediaLibraryDao.clearAndInsertLibrary(
mediaData.albumData.toAlbumEntity(),
mediaData.artistData.toArtistEntity(),
mediaData.genreData.toGenreEntity(),
mediaData.audioData.toMediaEntity(),
)
}

private suspend fun getAllMusicData() =
app.contentResolver.query2(
uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
Expand Down Expand Up @@ -44,20 +68,6 @@ class MediaLibraryScannerImpl(
parseGenreInfoCursor(cursor)
} ?: emptyList()

override suspend fun scanMediaData() = coroutineScope {
val musicDataDeferred = async { getAllMusicData() }
val albumDataDeferred = async { getAllAlbumData() }
val artistDataDeferred = async { getAllArtistData() }
val genreDataDeferred = async { getAllGenreData() }

MediaDataModel(
audioData = musicDataDeferred.await(),
albumData = albumDataDeferred.await(),
artistData = artistDataDeferred.await(),
genreData = genreDataDeferred.await(),
)
}

private fun parseGenreInfoCursor(cursor: Cursor): List<com.andannn.melodify.core.syncer.model.GenreData> {
val itemList = mutableListOf<com.andannn.melodify.core.syncer.model.GenreData>()

Expand Down Expand Up @@ -92,7 +102,6 @@ class MediaLibraryScannerImpl(
val numTracksIndex = cursor.getColumnIndex(MediaStore.Audio.Media.NUM_TRACKS)
val bitrateIndex = cursor.getColumnIndex(MediaStore.Audio.Media.BITRATE)
val yearIndex = cursor.getColumnIndex(MediaStore.Audio.Media.YEAR)
val trackIndex = cursor.getColumnIndex(MediaStore.Audio.Media.TRACK)
val composerIndex = cursor.getColumnIndex(MediaStore.Audio.Media.COMPOSER)
val genreIndex = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
cursor.getColumnIndex(MediaStore.Audio.Media.GENRE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package com.andannn.melodify.core.syncer.di
import com.andannn.melodify.core.syncer.MediaLibraryScanner
import com.andannn.melodify.core.syncer.MediaLibraryScannerImpl
import com.andannn.melodify.core.syncer.MediaLibrarySyncer
import com.andannn.melodify.core.syncer.MediaLibrarySyncerImpl
import com.andannn.melodify.core.syncer.MediaLibrarySyncerWrapper
import org.koin.core.module.Module
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.bind
import org.koin.dsl.module

actual val syncerModule: Module = module {
singleOf(::MediaLibrarySyncerImpl).bind(MediaLibrarySyncer::class)
singleOf(::MediaLibrarySyncerWrapper).bind(MediaLibrarySyncer::class)
singleOf(::MediaLibraryScannerImpl).bind(MediaLibraryScanner::class)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.andannn.melodify.core.syncer

import com.andannn.melodify.core.syncer.model.MediaDataModel

interface MediaLibraryScanner {
suspend fun scanMediaData(): MediaDataModel
suspend fun scanMediaDataAndSyncDatabase()
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ interface MediaLibrarySyncer {
suspend fun syncMediaLibrary(): Boolean
}

internal class MediaLibrarySyncerImpl(
internal class MediaLibrarySyncerWrapper(
private val mediaLibraryScanner: MediaLibraryScanner,
private val mediaLibraryDao: MediaLibraryDao,
) : MediaLibrarySyncer {
override suspend fun syncMediaLibrary(): Boolean {
Napier.d(tag = TAG) { "Syncing media library" }
Expand All @@ -36,14 +35,7 @@ internal class MediaLibrarySyncerImpl(

private suspend fun syncMediaLibraryInternal(): Boolean {
try {
val mediaData = mediaLibraryScanner.scanMediaData()

mediaLibraryDao.clearAndInsertLibrary(
mediaData.albumData.toAlbumEntity(),
mediaData.artistData.toArtistEntity(),
mediaData.genreData.toGenreEntity(),
mediaData.audioData.toMediaEntity(),
)
mediaLibraryScanner.scanMediaDataAndSyncDatabase()
return true
} catch (e: Exception) {
Napier.d(tag = TAG) { "Failed to sync media library: $e" }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
package com.andannn.melodify.core.syncer.di

import com.andannn.melodify.core.syncer.MediaLibrarySyncer
import com.andannn.melodify.core.syncer.MediaLibrarySyncerImpl
import org.koin.core.module.Module
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.bind
import org.koin.dsl.module

expect val syncerModule: Module
//= module {
// singleOf(::MediaLibrarySyncerImpl).bind(MediaLibrarySyncer::class)
//}
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,28 @@ class MediaLibraryScannerImpl(
private val mediaLibraryDao: MediaLibraryDao,
private val userSettingPreferences: UserSettingPreferences,
) : MediaLibraryScanner {
override suspend fun scanMediaData(): MediaDataModel {
override suspend fun scanMediaDataAndSyncDatabase() {

// 1: Get All media from database
// 2: Scan all files in library path and generated Key (generate hash from file path and last modify date).
// 3: Loop through all files in library path and create new media data list. rules:
// - If key exist in db, map db entity to AudioData (skip extract metadata).
// - If id not exist in db. extract metadata from file and create new AudioData
// 4: Group album from created AudioData list
// 4: Group album from created AlbumData list
// 5: Group artist from created AudioData list
// 6: Group genre from created AudioData list
// 6: Group genre from created GenreData list
// 7: Insert all data to database.

val allMediaEntity = mediaLibraryDao.getAllMediaFlow().first()
val mediaInDb = allMediaEntity.associateBy { it.id }

// TODO Get Path from DataStore after implement library path setting feature.
// val libraryPathSet = userSettingPreferences.userDate.first().libraryPath
val libraryPathSet = setOf(
"/mnt/chromeos/MyFiles/Shared"
"/Users/jiangqn/Documents"
)

// TODO: Scan file in worker thread.
val audioFileWithLastModifyDateList = scanAllLibraryAudioFile(libraryPathSet)

Napier.d(tag = TAG) { "scanMediaData: ${audioFileWithLastModifyDateList.size} files found" }
Expand Down Expand Up @@ -119,15 +121,21 @@ class MediaLibraryScannerImpl(
)
}

return MediaDataModel(
val mediaData = MediaDataModel(
audioData = audioDataListWitId,
albumData = albumDataList,
artistData = artistDataList,
genreData = genreDataList,
)
}


// TODO: Incremental comparison and insertion into the database, deleting outdated data.
mediaLibraryDao.clearAndInsertLibrary(
mediaData.albumData.toAlbumEntity(),
mediaData.artistData.toArtistEntity(),
mediaData.genreData.toGenreEntity(),
mediaData.audioData.toMediaEntity(),
)
}
}

private fun MediaEntity.toAudioData() = AudioData(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package com.andannn.melodify.core.syncer.di
import com.andannn.melodify.core.syncer.MediaLibraryScanner
import com.andannn.melodify.core.syncer.MediaLibraryScannerImpl
import com.andannn.melodify.core.syncer.MediaLibrarySyncer
import com.andannn.melodify.core.syncer.MediaLibrarySyncerImpl
import com.andannn.melodify.core.syncer.MediaLibrarySyncerWrapper
import org.koin.core.module.Module
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.bind
import org.koin.dsl.module

actual val syncerModule: Module = module {
singleOf(::MediaLibrarySyncerImpl).bind(MediaLibrarySyncer::class)
singleOf(::MediaLibrarySyncerWrapper).bind(MediaLibrarySyncer::class)
singleOf(::MediaLibraryScannerImpl).bind(MediaLibraryScanner::class)
}

0 comments on commit 18d9810

Please sign in to comment.