Skip to content

Commit

Permalink
core: improve tags extraction
Browse files Browse the repository at this point in the history
ref: $294
  • Loading branch information
MSOB7YY committed Aug 15, 2024
1 parent 408a4ef commit 0222ad4
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 64 deletions.
85 changes: 51 additions & 34 deletions android/app/src/main/kotlin/com/example/namida/FAudioTagger.kt
Original file line number Diff line number Diff line change
Expand Up @@ -247,33 +247,50 @@ public class FAudioTagger : FlutterPlugin, MethodCallHandler {
val tag: Tag? = audioFile.getTag()
if (tag != null) {
// -- Tags
val year = tag.getFirst(FieldKey.YEAR)
val album = tag.getFirst(FieldKey.ALBUM)
val albumArtist = tag.getFirst(FieldKey.ALBUM_ARTIST)
metadata["country"] = tag.getFirst(FieldKey.COUNTRY)
metadata["recordLabel"] = tag.getFirst(FieldKey.RECORD_LABEL)
metadata["language"] = tag.getFirst(FieldKey.LANGUAGE)
metadata["tempo"] = tag.getFirst(FieldKey.TEMPO)
metadata["tags"] = tag.getFirst(FieldKey.TAGS)
metadata["remixer"] = tag.getFirst(FieldKey.REMIXER)
val year = tag.getAll(FieldKey.YEAR)
val album = tag.getAll(FieldKey.ALBUM)
val albumArtist = tag.getAll(FieldKey.ALBUM_ARTIST)
metadata["country"] = tag.getAll(FieldKey.COUNTRY)
metadata["recordLabel"] = tag.getAll(FieldKey.RECORD_LABEL)
metadata["language"] = tag.getAll(FieldKey.LANGUAGE)
metadata["tempo"] = tag.getAll(FieldKey.TEMPO)
metadata["tags"] = tag.getAll(FieldKey.TAGS)
metadata["remixer"] = tag.getAll(FieldKey.REMIXER)
metadata["rating"] = tag.getFirst(FieldKey.RATING)
metadata["mood"] = tag.getFirst(FieldKey.MOOD)
metadata["mixer"] = tag.getFirst(FieldKey.MIXER)
metadata["djmixer"] = tag.getFirst(FieldKey.DJMIXER)
metadata["lyricist"] = tag.getFirst(FieldKey.LYRICIST)
metadata["lyrics"] = tag.getFirst(FieldKey.LYRICS)
metadata["mood"] = tag.getAll(FieldKey.MOOD)
metadata["mixer"] = tag.getAll(FieldKey.MIXER)
metadata["djmixer"] = tag.getAll(FieldKey.DJMIXER)
metadata["lyricist"] = tag.getAll(FieldKey.LYRICIST)
metadata["lyrics"] = tag.getAll(FieldKey.LYRICS)
metadata["discTotal"] = tag.getFirst(FieldKey.DISC_TOTAL)
metadata["discNumber"] = tag.getFirst(FieldKey.DISC_NO)
metadata["trackTotal"] = tag.getFirst(FieldKey.TRACK_TOTAL)
metadata["trackNumber"] = tag.getFirst(FieldKey.TRACK)
metadata["year"] = year
metadata["comment"] = tag.getFirst(FieldKey.COMMENT)
metadata["genre"] = tag.getFirst(FieldKey.GENRE)
metadata["composer"] = tag.getFirst(FieldKey.COMPOSER)
metadata["artist"] = tag.getFirst(FieldKey.ARTIST)
metadata["comment"] = tag.getAll(FieldKey.COMMENT)
metadata["genre"] = tag.getAll(FieldKey.GENRE)
metadata["composer"] = tag.getAll(FieldKey.COMPOSER)
metadata["artist"] = tag.getAll(FieldKey.ARTIST)
metadata["albumArtist"] = albumArtist
metadata["album"] = album
metadata["title"] = tag.getFirst(FieldKey.TITLE)
metadata["title"] = tag.getAll(FieldKey.TITLE)

try {
// -- filling missing id3v2 fields `TXXX`
val txxxRegex = """Description="([^"]*)"; Text="([^"]*)";""".toRegex()

tag.getFields("TXXX").forEach {
txxxRegex.findAll(it.toString()).forEach { matchResult ->
try {
val key = matchResult.groupValues[1]
if (metadata[key] == null) {
val value = matchResult.groupValues[2]
metadata[key] = value
}
} catch (_: Exception) {}
}
}
} catch (_: Exception) {}

if (extractArtwork) {
try {
Expand Down Expand Up @@ -407,28 +424,28 @@ public class FAudioTagger : FlutterPlugin, MethodCallHandler {
newTag.setField(newTag.createArtworkField(getImageData()))
} else if (newTag is FlacTag) {
newTag.setField(
newTag.createArtworkField(
getImageData(),
PictureTypes.DEFAULT_ID,
ImageFormats.MIME_TYPE_JPEG,
"artwork",
0,
0,
24,
0
)
newTag.createArtworkField(
getImageData(),
PictureTypes.DEFAULT_ID,
ImageFormats.MIME_TYPE_JPEG,
"artwork",
0,
0,
24,
0
)
)
} else if (newTag is VorbisCommentTag) {
val base64image = Base64.getEncoder().encodeToString(getImageData())
newTag.setField(newTag.createField(VorbisCommentFieldKey.COVERART, base64image))
newTag.setField(newTag.createField(VorbisCommentFieldKey.COVERARTMIME, "image/png"))
} else {
val cover =
if (artworkIsPath) ArtworkFactory.createArtworkFromFile(File(artwork as String))
else
ArtworkFactory.createArtworkFromMetadataBlockDataPicture(
MetadataBlockDataPicture(ByteBuffer.wrap(artwork as ByteArray))
)
if (artworkIsPath) ArtworkFactory.createArtworkFromFile(File(artwork as String))
else
ArtworkFactory.createArtworkFromMetadataBlockDataPicture(
MetadataBlockDataPicture(ByteBuffer.wrap(artwork as ByteArray))
)
newTag.setField(cover)
}
} else {
Expand Down
76 changes: 48 additions & 28 deletions lib/class/faudiomodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,53 @@ class FTags {
this.recordLabel,
});

static String? _listToString(List? list) {
if (list == null || list.isEmpty) return null;
if (list.length == 1) return list[0];
return list.join('; ');
}

// -- upper cased are the ones extracted manually.
factory FTags.fromMap(Map<String, dynamic> map) {
var lyricsList = map["lyrics"] as List?;
if (map["LYRICS"] is String) {
// -- recreating bcz its fixed length.
lyricsList = [
map["LYRICS"] as String,
...?lyricsList,
];
}

return FTags(
path: map["path"],
artwork: FArtwork.fromMap(map),
title: _listToString(map["title"]) ?? map["TITLE"],
album: _listToString(map["album"]) ?? map["ALBUM"],
albumArtist: _listToString(map["albumArtist"]) ?? map["ALBUMARTIST"],
artist: _listToString(map["artist"]) ?? map["ARTIST"],
composer: _listToString(map["composer"]) ?? map["COMPOSER"],
genre: _listToString(map["genre"]) ?? map["GENRE"],
trackNumber: map["trackNumber"] ?? map["TRACKNUMBER"],
trackTotal: map["trackTotal"] ?? map["TRACKTOTAL"],
discNumber: map["discNumber"] ?? map["DISCNUMBER"],
discTotal: map["discTotal"] ?? map["DISCTOTAL"],
lyrics: lyricsList?.firstWhereEff((e) => e is String ? e.isValidLRC() : false) ?? lyricsList?.firstOrNull,
comment: _listToString(map["comment"]) ?? map["COMMENT"],
year: _listToString(map["year"]) ?? map["YEAR"],
language: _listToString(map["language"]) ?? map["LANGUAGE"],
lyricist: _listToString(map["lyricist"]) ?? map["LYRICIST"],
djmixer: _listToString(map["djmixer"]) ?? map["DJMIXER"],
mixer: _listToString(map["mixer"]) ?? map["MIXER"],
mood: _listToString(map["mood"]) ?? map["MOOD"],
rating: map["rating"] ?? map["RATING"],
remixer: _listToString(map["remixer"]) ?? map["REMIXER"],
tags: _listToString(map["tags"]) ?? map["TAGS"],
tempo: _listToString(map["tempo"]) ?? map["TEMPO"],
country: _listToString(map["country"]) ?? map["COUNTRY"],
recordLabel: _listToString(map["recordLabel"]) ?? map["RECORDLABEL"] ?? map["label"] ?? map["LABEL"],
);
}

Map<String, dynamic> toMap() {
return <String, dynamic>{
"path": path,
Expand Down Expand Up @@ -163,34 +210,7 @@ class FAudioModel {

factory FAudioModel.fromMap(Map<String, dynamic> map) {
return FAudioModel(
tags: FTags(
path: map["path"],
artwork: FArtwork.fromMap(map),
title: map["title"],
album: map["album"],
albumArtist: map["albumArtist"],
artist: map["artist"],
composer: map["composer"],
genre: map["genre"],
trackNumber: map["trackNumber"],
trackTotal: map["trackTotal"],
discNumber: map["discNumber"],
discTotal: map["discTotal"],
lyrics: map["lyrics"],
comment: map["comment"],
year: map["year"],
language: map["language"],
lyricist: map["lyricist"],
djmixer: map["djmixer"],
mixer: map["mixer"],
mood: map["mood"],
rating: map["rating"],
remixer: map["remixer"],
tags: map["tags"],
tempo: map["tempo"],
country: map["country"],
recordLabel: map["recordLabel"],
),
tags: FTags.fromMap(map),
length: map["length"],
bitRate: map["bitRate"],
channels: map["channels"],
Expand Down
15 changes: 15 additions & 0 deletions lib/core/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ extension LRCParsingUtils on String {
} catch (_) {
try {
final res = LRCParserSmart(this).parseLines();
if (res.isEmpty) return null;
final lines = res
.map(
(e) => LrcLine(
Expand All @@ -416,6 +417,20 @@ extension LRCParsingUtils on String {
}
return null;
}

bool isValidLRC() {
bool valid = false;
try {
valid = Lrc.isValid(this);
} catch (_) {}
if (!valid) {
try {
final res = LRCParserSmart(this).parseLines();
valid = res.isNotEmpty;
} catch (_) {}
}
return valid;
}
}

extension TagFieldsUtils on TagField {
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/dialogs/set_lrc_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void showLRCSetDialog(Playable item, Color colorScheme) async {
availableLyrics.add(
LyricsModel(
lyrics: embedded,
synced: embedded.parseLRC() != null,
synced: embedded.isValidLRC(),
fromInternet: false,
isInCache: false,
file: null,
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: namida
description: A Beautiful and Feature-rich Music Player, With YouTube & Video Support Built in Flutter
publish_to: "none"
version: 3.9.16-beta+240815233
version: 3.9.2-beta+240815234

environment:
sdk: ">=3.4.0 <4.0.0"
Expand Down

0 comments on commit 0222ad4

Please sign in to comment.