From 72f17520321b1ace6e831d042577cdf9ebf4e6d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Font=C3=A1n?= Date: Sat, 11 May 2024 16:50:21 +0200 Subject: [PATCH] perf: Improved metadata handling logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gabriel Fontán --- .../tageditor/ID3MetadataEditorPage.kt | 91 +++--- .../ID3MetadataEditorPageViewModel.kt | 58 ++-- .../main/java/com/bobbyesp/ext/PropertyMap.kt | 43 +++ .../utilities/mediastore/AudioFileMetadata.kt | 259 +++--------------- gradle/libs.versions.toml | 2 +- 5 files changed, 152 insertions(+), 301 deletions(-) create mode 100644 app/utilities/src/main/java/com/bobbyesp/ext/PropertyMap.kt diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/ID3MetadataEditorPage.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/ID3MetadataEditorPage.kt index 7317abd..efe272b 100644 --- a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/ID3MetadataEditorPage.kt +++ b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/ID3MetadataEditorPage.kt @@ -54,8 +54,9 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.bobbyesp.ext.joinOrNullToString +import com.bobbyesp.ext.toAudioFileMetadata import com.bobbyesp.ext.toMinutes +import com.bobbyesp.ext.toModifiableMap import com.bobbyesp.metadator.R import com.bobbyesp.metadator.model.ParcelableSong import com.bobbyesp.metadator.presentation.common.LocalNavController @@ -65,6 +66,8 @@ import com.bobbyesp.ui.components.others.MetadataTag import com.bobbyesp.ui.components.text.LargeCategoryTitle import com.bobbyesp.ui.components.text.MarqueeText import com.bobbyesp.ui.components.text.PreConfiguredOutlinedTextField +import com.bobbyesp.utilities.mediastore.AudioFileMetadata.Companion.toAudioFileMetadata +import com.bobbyesp.utilities.mediastore.AudioFileMetadata.Companion.toPropertyMap import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -79,7 +82,8 @@ fun ID3MetadataEditorPage( val path = parcelableSong.localSongPath val scope = rememberCoroutineScope() - var propertiesCopy = viewModel.propertiesCopy.value + val metadata = viewState.metadata + val modifiablePropertyMap = viewState.metadata?.propertyMap?.toModifiableMap() var newArtworkAddress by remember { mutableStateOf(null) @@ -96,11 +100,15 @@ fun ID3MetadataEditorPage( rememberLauncherForActivityResult(contract = ActivityResultContracts.StartIntentSenderForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { scope.launch(Dispatchers.IO) { - viewModel.saveMetadata( - newMetadata = viewState.metadata?.copy( - propertyMap = propertiesCopy!!.toPropertyMap() - )!!, path = path!!, imageUri = newArtworkAddress - ) + modifiablePropertyMap?.let { + viewModel.saveMetadata( + newMetadata = viewState.metadata.copy( + propertyMap = it.toAudioFileMetadata().toPropertyMap() + ), + path = path!!, + imageUri = newArtworkAddress + ) + } } navController.popBackStack() } @@ -110,7 +118,7 @@ fun ID3MetadataEditorPage( fun saveInMediaStore(): Boolean = viewModel.saveMetadata( newMetadata = viewState.metadata?.copy( - propertyMap = propertiesCopy!!.toPropertyMap() + propertyMap = modifiablePropertyMap!!.toAudioFileMetadata().toPropertyMap() )!!, path = path!!, imageUri = newArtworkAddress ) { val intent = IntentSenderRequest.Builder(it).build() @@ -139,9 +147,6 @@ fun ID3MetadataEditorPage( }, actions = { IconButton(onClick = { scope.launch(Dispatchers.IO) { - val results = viewModel.getSpotifyResults( - propertiesCopy?.title?.joinToString() + propertiesCopy?.artist?.joinToString() - ) //TODO: Implement the search results } }) { @@ -191,11 +196,12 @@ fun ID3MetadataEditorPage( } is ID3MetadataEditorPageViewModel.Companion.ID3MetadataEditorPageState.Success -> { + //TODO: SOME FIELDS LIKE ARTIST MIGHT WANT TO BE SAVED IN DIFFERENT INDEXES OF THE ARRAY var showMediaStoreInfoDialog by remember { mutableStateOf(false) } val artworkUri = newArtworkAddress ?: parcelableSong.artworkPath - val songProperties = viewState.audioFileMetadata!! + val songProperties = metadata!!.propertyMap.toAudioFileMetadata() val audioStats = viewState.audioProperties!! val scrollState = rememberScrollState() @@ -293,39 +299,35 @@ fun ID3MetadataEditorPage( text = stringResource(id = R.string.general_tags) ) PreConfiguredOutlinedTextField( - value = songProperties.title.joinOrNullToString(), + value = songProperties.title, label = stringResource(id = R.string.title), modifier = Modifier.fillMaxWidth() ) { title -> - propertiesCopy?.title = arrayOf(title) + modifiablePropertyMap?.put("TITLE", title) } PreConfiguredOutlinedTextField( - value = songProperties.artist.joinOrNullToString(), + value = songProperties.artist, label = stringResource(id = R.string.artist), modifier = Modifier.fillMaxWidth() ) { artists -> - propertiesCopy?.artist = - artists.split(",").map { it.trim() }.toTypedArray() - + modifiablePropertyMap?.put("ARTIST", artists) } PreConfiguredOutlinedTextField( - value = songProperties.album.joinOrNullToString(), + value = songProperties.album, label = stringResource(id = R.string.album), modifier = Modifier.fillMaxWidth() ) { album -> - propertiesCopy?.album = arrayOf(album) + modifiablePropertyMap?.put("ALBUM", album) } PreConfiguredOutlinedTextField( - value = songProperties.albumArtist.joinOrNullToString(), + value = songProperties.albumArtist, label = stringResource(id = R.string.album_artist), modifier = Modifier.fillMaxWidth() ) { artists -> - propertiesCopy?.albumArtist = - artists.split(",").map { it.trim() }.toTypedArray() - + modifiablePropertyMap?.put("ALBUMARTIST", artists) } Column( @@ -335,40 +337,38 @@ fun ID3MetadataEditorPage( modifier = Modifier.fillMaxWidth(), ) { PreConfiguredOutlinedTextField( - value = songProperties.trackNumber.joinOrNullToString(), + value = songProperties.trackNumber, label = stringResource(id = R.string.track_number), modifier = Modifier.weight(0.5f) ) { trackNumber -> - propertiesCopy?.trackNumber = arrayOf(trackNumber) + modifiablePropertyMap?.put("TRACKNUMBER", trackNumber) } Spacer(modifier = Modifier.width(8.dp)) PreConfiguredOutlinedTextField( - value = songProperties.discNumber.joinOrNullToString(), + value = songProperties.discNumber, label = stringResource(id = R.string.disc_number), modifier = Modifier.weight(0.5f) ) { discNumber -> - propertiesCopy?.discNumber = arrayOf(discNumber) - + modifiablePropertyMap?.put("DISCNUMBER", discNumber) } } Row( modifier = Modifier.fillMaxWidth(), ) { PreConfiguredOutlinedTextField( - value = songProperties.date.joinOrNullToString(), + value = songProperties.date, label = stringResource(id = R.string.date), modifier = Modifier.weight(0.5f) ) { date -> - propertiesCopy?.date = arrayOf(date) - + modifiablePropertyMap?.put("DATE", date) } Spacer(modifier = Modifier.width(8.dp)) PreConfiguredOutlinedTextField( - value = songProperties.genre.joinOrNullToString(), + value = songProperties.genre, label = stringResource(id = R.string.genre), modifier = Modifier.weight(0.5f) ) { genre -> - propertiesCopy?.genre = arrayOf(genre) + modifiablePropertyMap?.put("GENRE", genre) } } } @@ -384,49 +384,46 @@ fun ID3MetadataEditorPage( modifier = Modifier.fillMaxWidth(), ) { PreConfiguredOutlinedTextField( - value = songProperties.composer.joinOrNullToString(), + value = songProperties.composer, label = stringResource(id = R.string.composer), modifier = Modifier.weight(0.5f) ) { composer -> - propertiesCopy?.composer = arrayOf(composer) + modifiablePropertyMap?.put("COMPOSER", composer) } Spacer(modifier = Modifier.width(8.dp)) PreConfiguredOutlinedTextField( - value = songProperties.lyricist.joinOrNullToString(), + value = songProperties.lyricist, label = stringResource(id = R.string.lyricist), modifier = Modifier.weight(0.5f) ) { lyricist -> - propertiesCopy?.lyricist = arrayOf(lyricist) + modifiablePropertyMap?.put("LYRICIST", lyricist) } } Row( modifier = Modifier.fillMaxWidth(), ) { PreConfiguredOutlinedTextField( - value = songProperties.conductor.joinOrNullToString(), + value = songProperties.conductor, label = stringResource(id = R.string.conductor), modifier = Modifier.weight(0.5f) ) { conductor -> - propertiesCopy?.conductor = arrayOf(conductor) + modifiablePropertyMap?.put("CONDUCTOR", conductor) } Spacer(modifier = Modifier.width(8.dp)) PreConfiguredOutlinedTextField( - value = songProperties.remixer.joinOrNullToString(), + value = songProperties.remixer, label = stringResource(id = R.string.remixer), modifier = Modifier.weight(0.5f) ) { remixer -> - propertiesCopy = propertiesCopy?.copy( - remixer = arrayOf(remixer) - ) + modifiablePropertyMap?.put("REMIXER", remixer) } } PreConfiguredOutlinedTextField( - value = songProperties.performer.joinOrNullToString(), + value = songProperties.performer, label = stringResource(id = R.string.performer), modifier = Modifier.fillMaxWidth() ) { performer -> - propertiesCopy?.performer = - performer.split(",").map { it.trim() }.toTypedArray() + modifiablePropertyMap?.put("PERFORMER", performer) } } } diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/ID3MetadataEditorPageViewModel.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/ID3MetadataEditorPageViewModel.kt index 4038fa1..9e0092c 100644 --- a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/ID3MetadataEditorPageViewModel.kt +++ b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/ID3MetadataEditorPageViewModel.kt @@ -6,13 +6,10 @@ import android.content.Context import android.net.Uri import android.os.Build import android.util.Log -import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.adamratzman.spotify.models.Track import com.bobbyesp.metadator.features.spotify.domain.repositories.SearchRepository -import com.bobbyesp.utilities.mediastore.AudioFileMetadata -import com.bobbyesp.utilities.mediastore.AudioFileMetadata.Companion.toAudioFileMetadata import com.bobbyesp.utilities.mediastore.MediaStoreReceiver import com.kyant.taglib.AudioProperties import com.kyant.taglib.AudioPropertiesReadStyle @@ -39,44 +36,43 @@ class ID3MetadataEditorPageViewModel @Inject constructor( private val mutablePageViewState = MutableStateFlow(PageViewState()) val pageViewState = mutablePageViewState.asStateFlow() - val propertiesCopy = mutableStateOf(null) - data class PageViewState( val metadata: Metadata? = null, - val audioFileMetadata: AudioFileMetadata? = null, val audioProperties: AudioProperties? = null, val state: ID3MetadataEditorPageState = ID3MetadataEditorPageState.Loading, ) suspend fun loadTrackMetadata(path: String) { updateState(ID3MetadataEditorPageState.Loading) - kotlin.runCatching { + runCatching { MediaStoreReceiver.getFileDescriptorFromPath(context, path, mode = "r")?.use { songFd -> val fd = songFd.dup()?.detachFd() ?: throw IllegalStateException("File descriptor is null") - val metadataDeferred = + val metadata = withContext(viewModelScope.coroutineContext + Dispatchers.IO) { async { TagLib.getMetadata( fd = fd, - readStyle = AudioPropertiesReadStyle.Fast ) - } - } + }.await() + } ?: throw IllegalStateException("Metadata is null") - val metadata = metadataDeferred.await() - - if (metadata == null) { - updateState(ID3MetadataEditorPageState.Error(Exception("Metadata is null"))) - return - } + val fd2 = songFd.dup()?.detachFd() + ?: throw IllegalStateException("File descriptor is null") + val audioProperties = + withContext(viewModelScope.coroutineContext + Dispatchers.IO) { + async { + TagLib.getAudioProperties( + fd = fd2, + readStyle = AudioPropertiesReadStyle.Fast + ) + }.await() + } ?: throw IllegalStateException("Audio properties are null") - updateMetadata(metadata) + updateStateMetadata(metadata, audioProperties) updateState(ID3MetadataEditorPageState.Success) - - propertiesCopy.value = metadata.propertyMap.toAudioFileMetadata() } }.onFailure { error -> Log.e( @@ -148,15 +144,11 @@ class ID3MetadataEditorPageViewModel @Inject constructor( description = "Song cover - Metadator", pictureType = "Cover (front)" ) - val saved = TagLib.savePictures( - fileDescriptorId, - pictures = arrayOf(picture) - ) - - if (saved) { - Log.i("ID3MetadataEditorPageViewModel", "Saved picture") - } else { - Log.e("ID3MetadataEditorPageViewModel", "Error while trying to save picture") + viewModelScope.launch(Dispatchers.IO) { + TagLib.savePictures( + fileDescriptorId, + pictures = arrayOf(picture) + ) } } @@ -178,12 +170,14 @@ class ID3MetadataEditorPageViewModel @Inject constructor( } } - private fun updateMetadata(metadata: Metadata? = null) { + private fun updateStateMetadata( + metadata: Metadata? = null, + audioProperties: AudioProperties? = null + ) { mutablePageViewState.update { it.copy( metadata = metadata, - audioFileMetadata = metadata?.propertyMap?.toAudioFileMetadata(), - audioProperties = metadata?.audioProperties + audioProperties = audioProperties ) } } diff --git a/app/utilities/src/main/java/com/bobbyesp/ext/PropertyMap.kt b/app/utilities/src/main/java/com/bobbyesp/ext/PropertyMap.kt new file mode 100644 index 0000000..3531316 --- /dev/null +++ b/app/utilities/src/main/java/com/bobbyesp/ext/PropertyMap.kt @@ -0,0 +1,43 @@ +package com.bobbyesp.ext + +import com.bobbyesp.utilities.mediastore.AudioFileMetadata + +typealias PropertyMap = HashMap> + +fun PropertyMap.toAudioFileMetadata(): AudioFileMetadata { + return AudioFileMetadata( + title = this["TITLE"]?.getOrNull(0), + artist = this["ARTIST"]?.getOrNull(0), + album = this["ALBUM"]?.getOrNull(0), + albumArtist = this["ALBUMARTIST"]?.getOrNull(0), + trackNumber = this["TRACKNUMBER"]?.getOrNull(0), + discNumber = this["DISCNUMBER"]?.getOrNull(0), + date = this["DATE"]?.getOrNull(0), + genre = this["GENRE"]?.getOrNull(0), + composer = this["COMPOSER"]?.getOrNull(0), + lyricist = this["LYRICIST"]?.getOrNull(0), + performer = this["PERFORMER"]?.getOrNull(0), + conductor = this["CONDUCTOR"]?.getOrNull(0), + remixer = this["REMIXER"]?.getOrNull(0), + comment = this["COMMENT"]?.getOrNull(0), + ) +} + +fun PropertyMap.toModifiableMap(): MutableMap { + return mutableMapOf( + "TITLE" to this["TITLE"]?.getOrNull(0), + "ARTIST" to this["ARTIST"]?.getOrNull(0), + "ALBUM" to this["ALBUM"]?.getOrNull(0), + "ALBUMARTIST" to this["ALBUMARTIST"]?.getOrNull(0), + "TRACKNUMBER" to this["TRACKNUMBER"]?.getOrNull(0), + "DISCNUMBER" to this["DISCNUMBER"]?.getOrNull(0), + "DATE" to this["DATE"]?.getOrNull(0), + "GENRE" to this["GENRE"]?.getOrNull(0), + "COMPOSER" to this["COMPOSER"]?.getOrNull(0), + "LYRICIST" to this["LYRICIST"]?.getOrNull(0), + "PERFORMER" to this["PERFORMER"]?.getOrNull(0), + "CONDUCTOR" to this["CONDUCTOR"]?.getOrNull(0), + "REMIXER" to this["REMIXER"]?.getOrNull(0), + "COMMENT" to this["COMMENT"]?.getOrNull(0), + ) +} \ No newline at end of file diff --git a/app/utilities/src/main/java/com/bobbyesp/utilities/mediastore/AudioFileMetadata.kt b/app/utilities/src/main/java/com/bobbyesp/utilities/mediastore/AudioFileMetadata.kt index bf5dcfb..2ff0987 100644 --- a/app/utilities/src/main/java/com/bobbyesp/utilities/mediastore/AudioFileMetadata.kt +++ b/app/utilities/src/main/java/com/bobbyesp/utilities/mediastore/AudioFileMetadata.kt @@ -1,245 +1,62 @@ package com.bobbyesp.utilities.mediastore +import com.bobbyesp.ext.PropertyMap import kotlinx.serialization.Serializable -typealias PropertyMap = HashMap> - @Serializable data class AudioFileMetadata( - // Basic tags - var title: Array? = null, - var album: Array? = null, - var artist: Array? = null, - var albumArtist: Array? = null, - var subtitle: Array? = null, - var trackNumber: Array? = null, - var discNumber: Array? = null, - var date: Array? = null, - var originalDate: Array? = null, - var genre: Array? = null, - var comment: Array? = null, - - // Sort names - var titleSort: Array? = null, - var albumSort: Array? = null, - var artistSort: Array? = null, - var albumArtistSort: Array? = null, - var composerSort: Array? = null, - - // Credits - var composer: Array? = null, - var lyricist: Array? = null, - var conductor: Array? = null, - var remixer: Array? = null, - var performer: Array? = null, - - // Other tags - var isrc: Array? = null, - var asin: Array? = null, - var bpm: Array? = null, - var encodedBy: Array? = null, - var mood: Array? = null, - var media: Array? = null, - var label: Array? = null, - var catalogNumber: Array? = null, - var barcode: Array? = null, - var releaseCountry: Array? = null, - var releaseStatus: Array? = null, - var releaseType: Array? = null + val title: String?, + val artist: String?, + val album: String?, + val albumArtist: String?, + val trackNumber: String?, + val discNumber: String?, + val date: String?, + val genre: String?, + val composer: String?, + val lyricist: String?, + val performer: String?, + val conductor: String?, + val remixer: String?, + val comment: String?, ) { companion object { - fun PropertyMap.toAudioFileMetadata(): AudioFileMetadata { + fun AudioFileMetadata.toPropertyMap(): PropertyMap { + return hashMapOf( + "TITLE" to arrayOf(title ?: ""), + "ARTIST" to arrayOf(artist ?: ""), + "ALBUM" to arrayOf(album ?: ""), + "ALBUMARTIST" to arrayOf(albumArtist ?: ""), + "TRACKNUMBER" to arrayOf(trackNumber ?: ""), + "DISCNUMBER" to arrayOf(discNumber ?: ""), + "DATE" to arrayOf(date ?: ""), + "GENRE" to arrayOf(genre ?: ""), + "COMPOSER" to arrayOf(composer ?: ""), + "LYRICIST" to arrayOf(lyricist ?: ""), + "CONDUCTOR" to arrayOf(conductor ?: ""), + "PERFORMER" to arrayOf(performer ?: ""), + "REMIXER" to arrayOf(remixer ?: ""), + "COMMENT" to arrayOf(comment ?: ""), + ) + } + + fun Map.toAudioFileMetadata(): AudioFileMetadata { return AudioFileMetadata( title = this["TITLE"], - album = this["ALBUM"], artist = this["ARTIST"], + album = this["ALBUM"], albumArtist = this["ALBUMARTIST"], - subtitle = this["SUBTITLE"], trackNumber = this["TRACKNUMBER"], discNumber = this["DISCNUMBER"], date = this["DATE"], - originalDate = this["ORIGINALDATE"], genre = this["GENRE"], - comment = this["COMMENT"], - titleSort = this["TITLESORT"], - albumSort = this["ALBUMSORT"], - artistSort = this["ARTISTSORT"], - albumArtistSort = this["ALBUMARTISTSORT"], - composerSort = this["COMPOSERSORT"], composer = this["COMPOSER"], lyricist = this["LYRICIST"], + performer = this["PERFORMER"], conductor = this["CONDUCTOR"], remixer = this["REMIXER"], - performer = this["PERFORMER"], - isrc = this["ISRC"], - asin = this["ASIN"], - bpm = this["BPM"], - encodedBy = this["ENCODEDBY"], - mood = this["MOOD"], - media = this["MEDIA"], - label = this["LABEL"], - catalogNumber = this["CATALOGNUMBER"], - barcode = this["BARCODE"], - releaseCountry = this["RELEASECOUNTRY"], - releaseStatus = this["RELEASESTATUS"], - releaseType = this["RELEASETYPE"] - ) - } - - fun AudioFileMetadata.deepCopy(): AudioFileMetadata { - return AudioFileMetadata( - title = title?.copyOf(), - album = album?.copyOf(), - artist = artist?.copyOf(), - albumArtist = albumArtist?.copyOf(), - subtitle = subtitle?.copyOf(), - trackNumber = trackNumber?.copyOf(), - discNumber = discNumber?.copyOf(), - date = date?.copyOf(), - originalDate = originalDate?.copyOf(), - genre = genre?.copyOf(), - comment = comment?.copyOf(), - titleSort = titleSort?.copyOf(), - albumSort = albumSort?.copyOf(), - artistSort = artistSort?.copyOf(), - albumArtistSort = albumArtistSort?.copyOf(), - composerSort = composerSort?.copyOf(), - composer = composer?.copyOf(), - lyricist = lyricist?.copyOf(), - conductor = conductor?.copyOf(), - remixer = remixer?.copyOf(), - performer = performer?.copyOf(), - isrc = isrc?.copyOf(), - asin = asin?.copyOf(), - bpm = bpm?.copyOf(), - encodedBy = encodedBy?.copyOf(), - mood = mood?.copyOf(), - media = media?.copyOf(), - label = label?.copyOf(), - catalogNumber = catalogNumber?.copyOf(), - barcode = barcode?.copyOf(), - releaseCountry = releaseCountry?.copyOf(), - releaseStatus = releaseStatus?.copyOf(), - releaseType = releaseType?.copyOf() + comment = this["COMMENT"], ) } } - - fun toPropertyMap(): PropertyMap { - return hashMapOf( - "TITLE" to title, - "ALBUM" to album, - "ARTIST" to artist, - "ALBUMARTIST" to albumArtist, - "SUBTITLE" to subtitle, - "TRACKNUMBER" to trackNumber, - "DISCNUMBER" to discNumber, - "DATE" to date, - "ORIGINALDATE" to originalDate, - "GENRE" to genre, - "COMMENT" to comment, - "TITLESORT" to titleSort, - "ALBUMSORT" to albumSort, - "ARTISTSORT" to artistSort, - "ALBUMARTISTSORT" to albumArtistSort, - "COMPOSERSORT" to composerSort, - "COMPOSER" to composer, - "LYRICIST" to lyricist, - "CONDUCTOR" to conductor, - "REMIXER" to remixer, - "PERFORMER" to performer, - "ISRC" to isrc, - "ASIN" to asin, - "BPM" to bpm, - "ENCODEDBY" to encodedBy, - "MOOD" to mood, - "MEDIA" to media, - "LABEL" to label, - "CATALOGNUMBER" to catalogNumber, - "BARCODE" to barcode, - "RELEASECOUNTRY" to releaseCountry, - "RELEASESTATUS" to releaseStatus, - "RELEASETYPE" to releaseType - ).filterValues { it != null } as PropertyMap - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as AudioFileMetadata - - if (!title.contentEquals(other.title)) return false - if (!album.contentEquals(other.album)) return false - if (!artist.contentEquals(other.artist)) return false - if (!albumArtist.contentEquals(other.albumArtist)) return false - if (!subtitle.contentEquals(other.subtitle)) return false - if (!trackNumber.contentEquals(other.trackNumber)) return false - if (!discNumber.contentEquals(other.discNumber)) return false - if (!date.contentEquals(other.date)) return false - if (!originalDate.contentEquals(other.originalDate)) return false - if (!genre.contentEquals(other.genre)) return false - if (!comment.contentEquals(other.comment)) return false - if (!titleSort.contentEquals(other.titleSort)) return false - if (!albumSort.contentEquals(other.albumSort)) return false - if (!artistSort.contentEquals(other.artistSort)) return false - if (!albumArtistSort.contentEquals(other.albumArtistSort)) return false - if (!composerSort.contentEquals(other.composerSort)) return false - if (!composer.contentEquals(other.composer)) return false - if (!lyricist.contentEquals(other.lyricist)) return false - if (!conductor.contentEquals(other.conductor)) return false - if (!remixer.contentEquals(other.remixer)) return false - if (!performer.contentEquals(other.performer)) return false - if (!isrc.contentEquals(other.isrc)) return false - if (!asin.contentEquals(other.asin)) return false - if (!bpm.contentEquals(other.bpm)) return false - if (!encodedBy.contentEquals(other.encodedBy)) return false - if (!mood.contentEquals(other.mood)) return false - if (!media.contentEquals(other.media)) return false - if (!label.contentEquals(other.label)) return false - if (!catalogNumber.contentEquals(other.catalogNumber)) return false - if (!barcode.contentEquals(other.barcode)) return false - if (!releaseCountry.contentEquals(other.releaseCountry)) return false - if (!releaseStatus.contentEquals(other.releaseStatus)) return false - if (!releaseType.contentEquals(other.releaseType)) return false - - return true - } - - override fun hashCode(): Int { - var result = title?.contentHashCode() ?: 0 - result = 31 * result + album.hashCode() - result = 31 * result + artist.hashCode() - result = 31 * result + albumArtist.hashCode() - result = 31 * result + subtitle.hashCode() - result = 31 * result + trackNumber.hashCode() - result = 31 * result + discNumber.hashCode() - result = 31 * result + date.hashCode() - result = 31 * result + originalDate.hashCode() - result = 31 * result + genre.hashCode() - result = 31 * result + comment.hashCode() - result = 31 * result + titleSort.hashCode() - result = 31 * result + albumSort.hashCode() - result = 31 * result + artistSort.hashCode() - result = 31 * result + albumArtistSort.hashCode() - result = 31 * result + composerSort.hashCode() - result = 31 * result + composer.hashCode() - result = 31 * result + lyricist.hashCode() - result = 31 * result + conductor.hashCode() - result = 31 * result + remixer.hashCode() - result = 31 * result + performer.hashCode() - result = 31 * result + isrc.hashCode() - result = 31 * result + asin.hashCode() - result = 31 * result + bpm.hashCode() - result = 31 * result + encodedBy.hashCode() - result = 31 * result + mood.hashCode() - result = 31 * result + media.hashCode() - result = 31 * result + label.hashCode() - result = 31 * result + catalogNumber.hashCode() - result = 31 * result + barcode.hashCode() - result = 31 * result + releaseCountry.hashCode() - result = 31 * result + releaseStatus.hashCode() - result = 31 * result + releaseType.hashCode() - return result - } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 84ff180..594b10e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -83,7 +83,7 @@ firebaseBom = "33.0.0" spotify-apiHandler = "4.1.1" #Others -taglib = "53f7581088" +taglib = "1.0.0-alpha17" #Tests junit = "4.13.2"