implement id3v2.3 tagging

This commit is contained in:
aliveoutside
2024-02-16 21:23:57 +03:00
parent e0d3f22f16
commit c1de68893c
6 changed files with 112 additions and 0 deletions
+2
View File
@@ -97,6 +97,8 @@ dependencies {
implementation 'net.sourceforge.streamsupport:streamsupport-minifuture:1.7.4'
implementation 'com.google.guava:guava:32.0.0-android'
implementation 'com.mpatric:mp3agic:0.9.1'
implementation fileTree(dir: 'libs', include: ['*.aar'])
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
}
@@ -355,4 +355,12 @@ public class Preferences {
if (MediaImageEncoder.needToSkipCompression()) return 100;
return origquality;
}
public static String metadataSeparator() {
return getPreferences().getString("metadata_separator", "; ");
}
public static void setMetadataSeparator(String separator) {
getPreferences().edit().putString("metadata_separator", separator).apply();
}
}
@@ -0,0 +1,55 @@
package ru.vtosters.lite.music.downloader;
import android.util.Log;
import com.mpatric.mp3agic.ID3v23Tag;
import com.mpatric.mp3agic.InvalidDataException;
import com.mpatric.mp3agic.Mp3File;
import com.mpatric.mp3agic.NotSupportedException;
import com.mpatric.mp3agic.UnsupportedTagException;
import com.vk.dto.music.MusicTrack;
import com.vk.dto.music.Artist;
import java.io.File;
import java.io.IOException;
import java.util.stream.Collectors;
import ru.vtosters.hooks.other.Preferences;
public class ID3Tagger {
public static void tag(File file, MusicTrack track) {
try {
// https://github.com/mpatric/mp3agic/issues/69#issuecomment-57897874
var oldFile = new File(file.getAbsolutePath().replace(".mp3", "_old.mp3"));
if (!file.renameTo(oldFile)) {
Log.e("ID3Tagger", "Failed to rename file");
return;
}
var mp3File = new Mp3File(oldFile);
if (mp3File.hasId3v2Tag()) {
var id3v2Tag = new ID3v23Tag();
if (track.L == null || track.I == null) {
id3v2Tag.setArtist(track.C);
} else {
var artists = track.L.stream().map(Artist::w1).collect(Collectors.joining(Preferences.metadataSeparator()));
id3v2Tag.setArtist(artists);
id3v2Tag.setAlbum(track.I.getTitle());
}
id3v2Tag.setTitle(M3UDownloader.getTitle(track));
mp3File.setId3v2Tag(id3v2Tag);
mp3File.save(file.getAbsolutePath());
if (!oldFile.delete()) {
Log.e("ID3Tagger", "Failed to delete file");
}
}
} catch (IOException | UnsupportedTagException | InvalidDataException |
NotSupportedException e) {
Log.e("ID3Tagger", "Failed to tag file", e);
}
}
}
@@ -6,9 +6,13 @@ import android.util.Log;
import com.google.android.exoplayer2.source.hls.playlist.e;
import com.google.android.exoplayer2.source.hls.playlist.f;
import com.google.android.exoplayer2.source.hls.playlist.f.a;
import com.mpatric.mp3agic.InvalidDataException;
import com.mpatric.mp3agic.Mp3File;
import com.mpatric.mp3agic.UnsupportedTagException;
import com.vk.dto.music.MusicTrack;
import java8.util.concurrent.CompletableFuture;
import java8.util.concurrent.CompletionException;
import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.music.cache.MusicCacheImpl;
import ru.vtosters.lite.music.converter.ts.MpegDemuxer;
import ru.vtosters.lite.music.converter.ts.TSMerger;
@@ -72,6 +76,11 @@ public class M3UDownloader
}
})
.thenRun(() -> callback.onProgress(10 + Math.round(80.0f * progress.addAndGet(1) / segments.size())))
.thenRun(() -> {
if (Preferences.getBoolValue("setMetaData", true)) {
ID3Tagger.tag(resultMp3, track);
}
})
.thenRun(() -> {
if (cache) {
MusicCacheImpl.addTrack(track);
@@ -162,6 +162,41 @@ public class MediaFragment extends TrackedMaterialPreferenceToolbarFragment {
});
findPreference("maxquality").setEnabled(Preferences.isEnableExternalOpening());
findPreference("metadataSeparator").setOnPreferenceClickListener(preference -> {
LinearLayout linearLayout = new LinearLayout(requireContext());
linearLayout.setOrientation(LinearLayout.VERTICAL);
EditText separator = new EditText(requireContext());
separator.setHint("По-умолчанию: ; с пробелом");
separator.setTextColor(ThemesUtils.getTextAttr());
separator.setHintTextColor(ThemesUtils.getSTextAttr());
separator.setBackgroundTintList(ThemesUtils.getAccenedColorStateList());
separator.setText(Preferences.metadataSeparator());
linearLayout.addView(separator);
separator.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) separator.getLayoutParams());
margin.setMargins(AndroidUtils.dp2px(20f), 0, AndroidUtils.dp2px(20f), 0);
separator.setLayoutParams(margin);
var t = new VkAlertDialog.Builder(requireContext())
.setTitle("Разделитель")
.setView(linearLayout)
.setPositiveButton("Сохранить", (dialog, which) -> {
if (separator.getText().toString().isEmpty()) {
AndroidUtils.sendToast("Разделитель не может быть пустым");
return;
}
Preferences.setMetadataSeparator(separator.getText().toString());
})
.setNegativeButton("Отмена", (dialog, which) -> dialog.cancel())
.show();
return true;
});
}
private void lastfmAuth(Context ctx) {
+3
View File
@@ -55,6 +55,9 @@
android:key="setMetaData"
android:summary="Сохранять id3v2 теги для песен для MP3"
android:title="Сохранять метадату песен"/>
<Preference
android:key="metadataSeparator"
android:title="Разделитель для id3v2 тегов"/>
<Preference
android:key="audio_download"
android:title="@string/audio_download_title"/>