From 25fcb84ea8039b7cfc798cfda5163f2d027738b1 Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Sat, 18 Mar 2023 14:28:53 +0530 Subject: [PATCH] fix: Fix corrupting of files when writing tags to unsupported files --- app/build.gradle | 2 +- .../tageditor/AbsTagEditorActivity.kt | 51 +++- .../activities/tageditor/TagWriter.kt | 263 +++++++++--------- app/src/main/res/values/strings.xml | 1 + 4 files changed, 171 insertions(+), 146 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index dae931b97..6bd881cf1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -154,7 +154,7 @@ dependencies { implementation "io.insert-koin:koin-core:$koin_version" implementation "io.insert-koin:koin-android:$koin_version" - def glide_version = '4.15.0' + def glide_version = '4.15.1' implementation "com.github.bumptech.glide:glide:$glide_version" ksp "com.github.bumptech.glide:ksp:$glide_version" implementation "com.github.bumptech.glide:okhttp3-integration:$glide_version" diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt index df973203e..dbdfb2b69 100755 --- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt @@ -46,6 +46,7 @@ import code.name.monkey.retromusic.model.ArtworkInfo import code.name.monkey.retromusic.model.AudioTagInfo import code.name.monkey.retromusic.repository.Repository import code.name.monkey.retromusic.util.logD +import code.name.monkey.retromusic.util.logE import com.google.android.material.button.MaterialButton import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.GlobalScope @@ -98,7 +99,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -107,7 +109,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TITLE) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -115,7 +118,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.COMPOSER) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -124,7 +128,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -133,7 +138,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ARTIST) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -142,7 +148,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -151,7 +158,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.GENRE) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -160,7 +168,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.YEAR) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -169,7 +178,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TRACK) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -178,7 +188,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.DISC_NO) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -187,7 +198,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.LYRICS) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -205,7 +217,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { ) } return null - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) return null } } @@ -356,9 +369,12 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { artworkInfo ) ) - val pendingIntent = MediaStore.createWriteRequest(contentResolver, getSongUris()) - launcher.launch(IntentSenderRequest.Builder(pendingIntent).build()) + if (cacheFiles.isNotEmpty()) { + val pendingIntent = + MediaStore.createWriteRequest(contentResolver, getSongUris()) + launcher.launch(IntentSenderRequest.Builder(pendingIntent).build()) + } } else { TagWriter.writeTagsToFiles( this@AbsTagEditorActivity, AudioTagInfo( @@ -396,9 +412,14 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { } } + private lateinit var audioFile: AudioFile + private fun getAudioFile(path: String): AudioFile { return try { - AudioFileIO.read(File(path)) + if (!this::audioFile.isInitialized) { + audioFile = AudioFileIO.read(File(path)) + } + audioFile } catch (e: Exception) { Log.e(TAG, "Could not read audio file $path", e) AudioFile() diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/TagWriter.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/TagWriter.kt index e4cf7fe89..b9d5f28dd 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/TagWriter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/TagWriter.kt @@ -7,6 +7,7 @@ import android.media.MediaScannerConnection import android.os.Build import android.util.Log import androidx.annotation.RequiresApi +import code.name.monkey.retromusic.R import code.name.monkey.retromusic.extensions.showToast import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener import code.name.monkey.retromusic.model.AudioTagInfo @@ -20,6 +21,7 @@ import org.jaudiotagger.audio.exceptions.CannotReadException import org.jaudiotagger.audio.exceptions.CannotWriteException import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException import org.jaudiotagger.audio.exceptions.ReadOnlyFileException +import org.jaudiotagger.tag.FieldDataInvalidException import org.jaudiotagger.tag.TagException import org.jaudiotagger.tag.images.AndroidArtwork import org.jaudiotagger.tag.images.Artwork @@ -31,9 +33,9 @@ class TagWriter { companion object { suspend fun scan(context: Context, toBeScanned: List?) { - if (toBeScanned == null || toBeScanned.isEmpty()) { + if (toBeScanned.isNullOrEmpty()) { Log.i("scan", "scan: Empty") - context.showToast( "Scan file from folder") + context.showToast("Scan file from folder") return } MediaScannerConnection.scanFile( @@ -50,150 +52,151 @@ class TagWriter { suspend fun writeTagsToFiles(context: Context, info: AudioTagInfo) { withContext(Dispatchers.IO) { - runCatching { - var artwork: Artwork? = null - var albumArtFile: File? = null - if (info.artworkInfo?.artwork != null) { - try { - albumArtFile = createAlbumArtFile(context).canonicalFile - info.artworkInfo.artwork.compress( - Bitmap.CompressFormat.JPEG, - 100, - albumArtFile.outputStream() - ) - artwork = AndroidArtwork.createArtworkFromFile(albumArtFile) - } catch (e: IOException) { - e.printStackTrace() - } + var artwork: Artwork? = null + var albumArtFile: File? = null + if (info.artworkInfo?.artwork != null) { + try { + albumArtFile = createAlbumArtFile(context).canonicalFile + info.artworkInfo.artwork.compress( + Bitmap.CompressFormat.JPEG, + 100, + albumArtFile.outputStream() + ) + artwork = AndroidArtwork.createArtworkFromFile(albumArtFile) + } catch (e: IOException) { + e.printStackTrace() } - var wroteArtwork = false - var deletedArtwork = false - for (filePath in info.filePaths!!) { - try { - val audioFile = AudioFileIO.read(File(filePath)) - val tag = audioFile.tagOrCreateAndSetDefault - if (info.fieldKeyValueMap != null) { - for ((key, value) in info.fieldKeyValueMap) { - try { - tag.setField(key, value) - } catch (e: Exception) { - e.printStackTrace() - } - } - } - if (info.artworkInfo != null) { - if (info.artworkInfo.artwork == null) { - tag.deleteArtworkField() - deletedArtwork = true - } else if (artwork != null) { - tag.deleteArtworkField() - tag.setField(artwork) - wroteArtwork = true - } - } - audioFile.commit() - } catch (e: CannotReadException) { - e.printStackTrace() - } catch (e: IOException) { - e.printStackTrace() - } catch (e: CannotWriteException) { - e.printStackTrace() - } catch (e: TagException) { - e.printStackTrace() - } catch (e: ReadOnlyFileException) { - e.printStackTrace() - } catch (e: InvalidAudioFrameException) { - e.printStackTrace() - } - } - if (wroteArtwork) { - insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path) - } else if (deletedArtwork) { - deleteAlbumArt(context, info.artworkInfo!!.albumId) - } - scan(context, info.filePaths) - }.onFailure { - it.printStackTrace() } + var wroteArtwork = false + var deletedArtwork = false + for (filePath in info.filePaths!!) { + try { + val audioFile = AudioFileIO.read(File(filePath)) + val tag = audioFile.tagOrCreateAndSetDefault + if (info.fieldKeyValueMap != null) { + for ((key, value) in info.fieldKeyValueMap) { + try { + tag.setField(key, value) + } catch (e: FieldDataInvalidException) { + withContext(Dispatchers.Main) { + context.showToast(R.string.could_not_write_tags_to_file) + } + return@withContext listOf() + } catch (e: Exception) { + e.printStackTrace() + } + } + } + if (info.artworkInfo != null) { + if (info.artworkInfo.artwork == null) { + tag.deleteArtworkField() + deletedArtwork = true + } else if (artwork != null) { + tag.deleteArtworkField() + tag.setField(artwork) + wroteArtwork = true + } + } + audioFile.commit() + } catch (e: CannotReadException) { + e.printStackTrace() + } catch (e: IOException) { + e.printStackTrace() + } catch (e: CannotWriteException) { + e.printStackTrace() + } catch (e: TagException) { + e.printStackTrace() + } catch (e: ReadOnlyFileException) { + e.printStackTrace() + } catch (e: InvalidAudioFrameException) { + e.printStackTrace() + } + } + if (wroteArtwork) { + insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path) + } else if (deletedArtwork) { + deleteAlbumArt(context, info.artworkInfo!!.albumId) + } + scan(context, info.filePaths) } } - @RequiresApi(Build.VERSION_CODES.R) suspend fun writeTagsToFilesR(context: Context, info: AudioTagInfo): List = withContext(Dispatchers.IO) { val cacheFiles = mutableListOf() - runCatching { - var artwork: Artwork? = null - var albumArtFile: File? = null - if (info.artworkInfo?.artwork != null) { - try { - albumArtFile = createAlbumArtFile(context).canonicalFile - info.artworkInfo.artwork.compress( - Bitmap.CompressFormat.JPEG, - 100, - albumArtFile.outputStream() - ) - artwork = AndroidArtwork.createArtworkFromFile(albumArtFile) - } catch (e: IOException) { - e.printStackTrace() - } + var artwork: Artwork? = null + var albumArtFile: File? = null + if (info.artworkInfo?.artwork != null) { + try { + albumArtFile = createAlbumArtFile(context).canonicalFile + info.artworkInfo.artwork.compress( + Bitmap.CompressFormat.JPEG, + 100, + albumArtFile.outputStream() + ) + artwork = AndroidArtwork.createArtworkFromFile(albumArtFile) + } catch (e: IOException) { + e.printStackTrace() } - var wroteArtwork = false - var deletedArtwork = false - for (filePath in info.filePaths!!) { - try { - val originFile = File(filePath) - val cacheFile = File(context.cacheDir, originFile.name) - cacheFiles.add(cacheFile) - originFile.inputStream().use { input -> - cacheFile.outputStream().use { output -> - input.copyTo(output) - } + } + var wroteArtwork = false + var deletedArtwork = false + for (filePath in info.filePaths!!) { + try { + val originFile = File(filePath) + val cacheFile = File(context.cacheDir, originFile.name) + cacheFiles.add(cacheFile) + originFile.inputStream().use { input -> + cacheFile.outputStream().use { output -> + input.copyTo(output) } - val audioFile = AudioFileIO.read(cacheFile) - val tag = audioFile.tagOrCreateAndSetDefault - if (info.fieldKeyValueMap != null) { - for ((key, value) in info.fieldKeyValueMap) { - try { - tag.setField(key, value) - } catch (e: Exception) { - e.printStackTrace() + } + val audioFile = AudioFileIO.read(cacheFile) + val tag = audioFile.tagOrCreateAndSetDefault + if (info.fieldKeyValueMap != null) { + for ((key, value) in info.fieldKeyValueMap) { + try { + tag.setField(key, value) + } catch (e: FieldDataInvalidException) { + withContext(Dispatchers.Main) { + context.showToast(R.string.could_not_write_tags_to_file) } + return@withContext listOf() + } catch (e: Exception) { + e.printStackTrace() } } - if (info.artworkInfo != null) { - if (info.artworkInfo.artwork == null) { - tag.deleteArtworkField() - deletedArtwork = true - } else if (artwork != null) { - tag.deleteArtworkField() - tag.setField(artwork) - wroteArtwork = true - } - } - audioFile.commit() - } catch (e: CannotReadException) { - e.printStackTrace() - } catch (e: IOException) { - e.printStackTrace() - } catch (e: CannotWriteException) { - e.printStackTrace() - } catch (e: TagException) { - e.printStackTrace() - } catch (e: ReadOnlyFileException) { - e.printStackTrace() - } catch (e: InvalidAudioFrameException) { - e.printStackTrace() } + if (info.artworkInfo != null) { + if (info.artworkInfo.artwork == null) { + tag.deleteArtworkField() + deletedArtwork = true + } else if (artwork != null) { + tag.deleteArtworkField() + tag.setField(artwork) + wroteArtwork = true + } + } + audioFile.commit() + } catch (e: CannotReadException) { + e.printStackTrace() + } catch (e: IOException) { + e.printStackTrace() + } catch (e: CannotWriteException) { + e.printStackTrace() + } catch (e: TagException) { + e.printStackTrace() + } catch (e: ReadOnlyFileException) { + e.printStackTrace() + } catch (e: InvalidAudioFrameException) { + e.printStackTrace() } - if (wroteArtwork) { - insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path) - } else if (deletedArtwork) { - deleteAlbumArt(context, info.artworkInfo!!.albumId) - } - }.onFailure { - it.printStackTrace() + } + if (wroteArtwork) { + insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path) + } else if (deletedArtwork) { + deleteAlbumArt(context, info.artworkInfo!!.albumId) } cacheFiles } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0e6eaba7a..e9609c7c1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -562,4 +562,5 @@ You have to select at least one category. You will be forwarded to the issue tracker website. Your account data is only used for authentication. + Could not write tags to the music file!